Web

PHP 8.3: Include Broken by Short Open Tags - Fix Now

After upgrading to PHP 8.3, short open tags (<? ?>) are no longer parsed and show up as HTML comments. Replace them with <?php ?> to fix include execution.

1 answer 1 view

After upgrading from PHP 7.3 to PHP 8.3, a PHP include using the short open tag stopped working. In PHP 7.3 the following line worked:

php
<?include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html');?>

But in PHP 8.3 that line is output as an HTML comment on .php pages (and therefore not executed), for example:

html
<!--<?include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html');?> -->

On .html pages it still works. What changed in PHP 8.3 and how can I fix this? Should I enable short_open_tag, switch to the full tag (<?php include ... ?>), or adjust server configuration? What is the recommended solution and why?

After upgrading to PHP 8.3, your php include using short open tags like <?include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html');?> fails because short open tags were fully removed from the language. PHP now parses <? as an XML declaration, turning the whole line into an HTML comment like <!--<?include ...?>-->, so it’s never executed on .php pages. The recommended fix? Replace it with full tags: <?php include ...;?>. Don’t bother trying to enable short_open_tag—it’s gone for good, and this change ensures better compatibility across servers.


Contents


What Changed in PHP 8.3 Regarding Short Open Tags

Upgrading from PHP 7.3 to PHP 8.3? That php include line worked fine before, but now it’s dead silent—or worse, showing up as a comment. Here’s the deal: short open tags (<? ... ?>) got the boot.

This wasn’t some overnight whim. The process started way back. In PHP 7.4, they slapped a deprecation notice on short tags when short_open_tag was on. By PHP 8.0, the parser stopped recognizing <? as PHP code entirely—it began treating it like XML. And in PHP 8.3, the short_open_tag ini directive vanished completely. No more toggling it on or off.

Why the shift? Short tags always depended on server settings, so your code might run on one host but bomb on another. Plus, <? clashes with XML declarations like <?xml ...?>, creating parsing headaches in mixed HTML/PHP files. The official PHP RFC on deprecating short tags lays it out: files with <?include ...?> now get rendered as plain text or comments, never parsed.

Think about it—your SSI include for /ssi/h1.html? In PHP 8.3, it’s just decoration.


Why Your Code Outputs as an HTML Comment

Ever wonder why that line spits out <!--<?include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html');?>-->? It’s not a bug; it’s by design.

Browsers (and PHP’s parser) see <? without php and assume it’s an XML processing instruction. Everything until ?> gets wrapped in HTML comment syntax for safety. On .php pages, the server processes the file through PHP first, hits this unrecognized tag, and outputs the comment. Boom—no include happens.

This bites especially hard for server-side includes (SSI) mimicking old Apache includes. In PHP 7.3, short_open_tag = On let it fly. Post-upgrade? Nope. Stack Overflow users hit this wall hard, confirming PHP 8.3 treats short tags as comments across the board: one detailed thread explains it perfectly.

Quick test: Drop that line in a fresh PHP 8.3 file. You’ll see the comment. Frustrating, right?


short_open_tag Directive: Deprecated and Removed

Should you enable short_open_tag? Save your breath. It’s not just disabled—it’s erased.

In older PHP like 7.3, you’d edit php.ini, set short_open_tag = On, restart Apache or PHP-FPM, and done. But the PHP manual on tags has warned for years: “As short tags can be disabled, it’s recommended to only use the normal tags (<?php and ?>) to maximise compatibility.”

PHP 8.3 seals the deal—no ini setting, no .htaccess flag, nothing. Even if you hack it in php.ini, the parser ignores it. Community reports from SitePoint and Server Fault echo this: attempts to flip it on fail post-upgrade.

One silver lining: the short echo tag <?= stays forever (enabled since PHP 5.4). But for <?include? Full tags only.


.php vs .html Pages: Why the Difference?

Weird part: it “works” on .html pages. Why?

.php files go through PHP’s engine. It scans for tags, doesn’t recognize short open, outputs as comment.

.html files? Often handled by Apache’s mod_include (SSI) or similar. If your server config passes <? ... ?> to the SSI processor (like XBitHack or IncludesNOEXEC), it treats it as a directive—bypassing PHP entirely. No parsing conflict.

But this is flaky. Relying on .html for PHP includes? That’s a house of cards. Upgrade your server, tweak configs, and poof—gone. Stick to .php with proper tags for consistency.


Here’s the no-nonsense solution: rewrite to <?php include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html'); ?>.

Why full tags? Universal compatibility—no ini roulette. The PHP manual pushes this hard. Your code:

Before (broken in PHP 8.3):

php
<?include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html');?>

After (works everywhere):

php
<?php include ($_SERVER['DOCUMENT_ROOT'].'/ssi/h1.html'); ?>

Note the space after include—good habit, avoids warnings. For output buffering issues with includes, wrap in ob_start() if needed, but usually not.

Bulk fix? Grep your codebase: grep -r '<?(?!php|xml)' . --include="*.php" (finds non-php/xml short tags). Sed replace: sed -i 's/<?/<?php /g' files.php. Test thoroughly.

This fixes php include errors instantly. No server tweaks required.


Server Configuration Checks and Common Pitfalls

Double-checking your setup? Smart move, even if tags are the culprit.

  1. Verify PHP version: php -v. Confirm PHP 8.3.
  2. phpinfo(): Create info.php with <?php phpinfo(); ?>, check for old short_open_tag ghosts (won’t be there).
  3. Restart everything: Apache/Nginx and PHP-FPM. Config changes stick only after.
  4. Multi-PHP setups (e.g., Ubuntu with Ondřej repos)? Ensure the right FPM pool serves your site.
  5. .htaccess or virtual host forcing SSI? Might explain .html behavior—disable if possible.

Pitfalls: Some hosts lag on upgrades, mixing PHP versions. Or caching proxies serving old output. Clear everything.

Still stuck? Logs: error_log might show “include failed” if paths are off, but yours is a tag issue.


Best Practices for PHP Includes and Upgrades

Short tags were always a bad idea. XML conflicts, portability woes—avoided by pros for a decade.

Upgrade tips for PHP 8.3:

  • Audit all files for short tags early.
  • Use require_once over include for critical files (halts on failure).
  • Paths: $_SERVER['DOCUMENT_ROOT'] is fine, but consider __DIR__ . '/../ssi/h1.html' for relatives.
  • Composer autoload for modern apps.
  • Test with php -l file.php for syntax.

Future-proof: Full tags, strict error reporting (error_reporting(E_ALL);). Your SSI setup? Migrate to proper PHP partials or Twig for templates.

And <?= for echoes? Keep it—it’s safe.


Sources

  1. PHP RFC: Deprecate PHP Short Open Tags
  2. PHP Manual: PHP Tags
  3. Stack Overflow: How to enable PHP short tags?
  4. Stack Overflow: PHP 8 not revealing short_open_tag setting
  5. SitePoint: Short Open Tags ON but Not Working
  6. Server Fault: PHP short_open_tag Won’t Enable

Conclusion

PHP 8.3 killed short open tags to kill ambiguity and boost portability—your php include breaking as an HTML comment is the direct fallout. Switch to <?php include ...; ?> everywhere; it’s the official, foolproof fix that works on any server without config hacks. Ditch short_open_tag dreams, audit your code, and you’ll be solid for future upgrades too.

Authors
Verified by moderation
Moderation
PHP 8.3: Include Broken by Short Open Tags - Fix Now