Short Open Tags History & Why to Avoid
debt(d3/e1/b3/t5)
Closest to 'default linter catches the common case' (d3). The detection_hints list phpcs and rector — both widely used default-level PHP tooling — and the code_pattern `^<\?[^p=]` is simple enough that phpcs/PSR-1 sniffs catch it automatically in a standard CI pipeline.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is explicit: replace all `<?` with `<?php`. This is a mechanical find-and-replace, automatable with rector or a sed one-liner, with no logic changes required.
Closest to 'localised tax' (b3). The issue applies to web and cli contexts broadly, but the fix is syntactic and confined to file headers/open tags. It doesn't impose an ongoing architectural weight; once replaced, the debt is gone. Slightly elevated from b1 because inconsistent mixing across many files in a legacy codebase does slow down reviewers.
Closest to 'notable trap' (t5). The misconception field states it exactly: developers assume `<?=` is the same as `<?` and therefore believe all short tags are affected by `short_open_tag=Off`. In reality `<?=` has been standardised since PHP 5.4 and is always available. This is a documented, well-known gotcha that most PHP developers eventually learn, matching the t5 anchor.
TL;DR
Explanation
PHP has always supported <? ?> (short_open_tag) and <?= ?> (short_echo_tag). Problems: (1) short_open_tag=Off on many PHP installs — code breaks silently. (2) <?xml conflicts with PHP short tags when short_open_tag=On. (3) Different defaults across PHP versions. PHP 5.4 made <?= always available regardless of short_open_tag. PHP 7+ recommends always using <?php. In templates, <?= $var ?> is acceptable and standardised (Blade, Twig use it). But <? for code blocks should always be avoided. PSR-1 requires <?php or <?=.
Common Misconception
Why It Matters
Common Mistakes
- Using <? instead of <?php for code blocks.
- Not knowing <?= is always available since PHP 5.4.
- Mixing short tags and full tags inconsistently.
Code Examples
<? // Breaks on servers with short_open_tag=Off
$users = getUsers();
foreach ($users as $user): ?>
<p><?=$user->name?></p>
<?php // Always works
$users = getUsers();
foreach ($users as $user): ?>
<p><?= htmlspecialchars($user->getName()) ?></p>
<?php endforeach; ?>