In PHP, what is the difference between the <?= short echo tag and short open tags, and which one is safe to use?
answer
- <?= always available
- <? depends on short_open_tag
- built-in On, shipped ini files Off
- clashes with <?xml
- not changeable with ini_set()
basics
~10 ssolid answer
~40 s`<?= $x ?>` is shorthand for `<?php echo $x ?>` and is **always available**; the `short_open_tag` directive does not affect it. The bare **short open tag** `<?` is different: it only works when `short_open_tag` is enabled. The built-in default is On, but both `php.ini-production` and `php.ini-development` shipped with PHP 8.5 set it to **Off**, and PHP can be built with `--disable-short-tags`. The directive is `PHP_INI_SYSTEM|PHP_INI_PERDIR`, so code cannot switch it on with `ini_set()`. When it is off, `<? ... ?>` is not parsed: the code is sent to the browser as text. When it is on, an inline `<?xml ... ?>` declaration is parsed as PHP. So: use `<?php` for code and `<?=` for output in templates, never `<?`.
go deeper
Recall that <?= is always safe for printing in templates and that bare <? depends on a setting, so code should use <?php.
Explain short_open_tag: built-in default On, shipped ini files Off, changeable only in php.ini or per directory, and the <?xml clash.
Assess the risk in a legacy codebase: short tags silently leak source when a server's ini differs, so convert them and add a check in CI.
Remove environment-dependent syntax from the codebase entirely rather than standardising the setting across every server and container image.
## Three opening tags PHP recognises three ways to enter PHP mode: | Tag | Meaning | Depends on configuration | |---|---|---| | `<?php` | the normal opening tag | no | | `<?=` | short echo: `<?= expr ?>` is `<?php echo expr ?>` | no, always available | | `<?` | short open tag, same as `<?php` | yes, only when `short_open_tag` is on | The manual recommends using only `<?php ?>` and `<?= ?>` "to maximise compatibility". ## The short echo tag `<?=` exists for templates, where most PHP blocks just print a value: ```php <li><?= htmlspecialchars($dish['name']) ?>: <?= number_format($dish['price'], 2) ?></li> ``` Facts worth knowing: - It is **always enabled**. The ini documentation says `short_open_tag` "does not affect the shorthand `<?=`, which is always available". - It accepts what `echo` accepts, including several comma-separated expressions. - It does not escape anything. Escaping output for HTML is a separate responsibility. ## The short open tag and short_open_tag The bare `<?` tag is controlled by the `short_open_tag` directive: - **Built-in default**: On (unless PHP was compiled with `--disable-short-tags`). - **`php.ini-production` and `php.ini-development`** shipped with 8.5: both set `short_open_tag = Off`. - **Changeable mode**: `PHP_INI_SYSTEM|PHP_INI_PERDIR`. It can be set in `php.ini` or per directory, but not with `ini_set()` at runtime; by then the file has already been parsed anyway. So whether `<?` works depends on which ini file a server loaded, which is exactly the kind of environmental difference that breaks a deploy. ## What goes wrong **Short tags off, code uses `<?`.** The parser does not see an opening tag, so `<? echo $total; ?>` is plain inline text. The browser receives the PHP source. Depending on the page, that can leak logic, paths or credentials written in the template. **Short tags on, template contains XML.** An XML declaration such as `<?xml version="1.0"?>` starts with `<?`, so PHP treats `xml version=...` as PHP code and fails with a parse error. The ini documentation describes disabling `short_open_tag` for exactly this reason, or printing the declaration from PHP: ```php <?php echo '<?xml version="1.0" encoding="UTF-8"?>', "\n"; ?> ``` ## A short history of tags PHP once accepted more opening tags than it does now: - **ASP-style tags** (`<% %>`, controlled by the `asp_tags` directive) and **script tags** (`<script language="php">`) were removed in PHP 7.0, together with the `asp_tags` directive. - The short open tag `<?` survived and is still controlled by `short_open_tag` in 8.5. - `<?=` is independent of that directive and is the only short form worth using. Old templates are where bare `<?` still turns up, usually written when a server had the directive on. ## Recommendations 1. Write `<?php` for every block of code, in every file. 2. Use `<?=` freely in templates; it is portable and reads well. 3. Never write bare `<?`, and do not rely on `short_open_tag` being on. 4. When auditing old code, search for `<?` not followed by `php`, `=` or `xml`, and convert it; coding-standard tools can flag it. ## Why interviewers ask The question separates candidates who have maintained older PHP templates, where `<?` was common, from those who only know modern code. The expected answer is short: `<?=` always works, `<?` depends on `short_open_tag`, the shipped ini files turn it off, so only `<?php` and `<?=` are portable.
- Can a script enable short_open_tag with ini_set() before using <? in an included template?No. `short_open_tag` is changeable only in `php.ini` or per directory (`PHP_INI_SYSTEM|PHP_INI_PERDIR`), not with `ini_set()`. Tags are also recognised when a file is compiled, so the setting has to be in place before PHP parses the template. The portable fix is to rewrite `<?` as `<?php`.
- What does a visitor see when a template uses <? and the server has short_open_tag off?The PHP code itself. Without the directive, `<?` is not an opening tag, so everything up to the next real tag is inline text and is sent as-is. The page shows or hides the source depending on the HTML around it, but it is always in the response, which can expose logic or configuration.
The short echo tag is like a universal power plug that fits every socket; the bare short tag is a plug that fits only in rooms where someone installed an adapter, and most rooms today have none.
saying these in an interview costs you the question
- <?= only works when short_open_tag is enabled.
- short_open_tag is off by default in PHP's built-in configuration.
- A script can enable short tags at runtime with ini_set().
- When short tags are disabled, PHP throws a parse error on <?.
- <?= escapes HTML automatically.