[php] Why would one omit the close tag?

It's a newbie coding style recommendation, well-intentioned, and advised by the manual.

  • Eschewing ?> however solves just a trickle of the common headers already sent causes (raw output, BOM, notices, etc.) and their follow-up problems.

  • PHP actually contains some magic to eat up single linebreaks after the ?> closing token. Albeit that has historic issues, and leaves newcomers still susceptible to flaky editors and unawarely shuffling in other whitespace after ?>.

  • Stylistically some developers prefer to view <?php and ?> as SGML tags / XML processing instructions, implying the balance consistency of a trailing close token. (Which btw, is useful for dependency-conjoining class includes to supplant inefficient file-by-file autoloading.)

  • Somewhat uncommonly the opening <?php is characterized as PHPs shebang (and fully feasible per binfmt_misc), thereby validating the redundancy of a corresponding close tag.

  • There's an obvious advise discrepancy between classic PHP syntax guides mandating ?>\n and the more recent ones (PSR-2) agreeing on omission.
    (For the record: Zend Framework postulating one over the other does not imply its inherent superiority. It's a misconception that experts were drawn to / target audience of unwieldy APIs).

  • SCMs and modern IDEs provide builtin solutions mostly alleviating close tag caretaking.

Discouraging any use of the ?> close tag merely delays explaining basic PHP processing behaviour and language semantics to eschew infrequent issues. It is practical still for collaborative software development due to proficiency variations in participants.

Close tag variations

  • The regular ?> close tag is also known as T_CLOSE_TAG, or thus "close token".

  • It comprises a few more incarnations, because of PHPs magic newline eating:

    ?>\n (Unix linefeed)

    ?>\r (Carriage return, classic MACs)

    ?>\r\n (CR/LF, on DOS/Win)

    PHP doesn't support the Unicode combo linebreak NEL (U+0085) however.

    Early PHP versions had IIRC compile-ins limiting platform-agnosticism somewhat (FI even just used > as close marker), which is the likely historic origin of the close-tag-avoidance.

  • Often overlooked, but until PHP7 removes them, the regular <?php opening token can be validly paired with the rarely used </script> as odd closing token.

  • The "hard close tag" isn't even one -- just made that term up for analogy. Conceptionally and usage-wise __halt_compiler should however be recognized as close token.

    __HALT_COMPILER();
    ?>
    

    Which basically has the tokenizer discard any code or plain HTML sections thereafter. In particular PHAR stubs make use of that, or its redundant combination with ?> as depicted.

  • Likewise does a void return; infrequently substitute in include scripts, rendering any ?> with trailing whitespace noneffective.

  • Then there are all kinds of soft / faux close tag variations; lesser known and seldomly used, but usually per commented-out tokens:

    • Simple spacing // ? > to evade detection by PHPs tokenizer.

    • Or fancy Unicode substitutes // ?? (U+FE56 SMALL QUESTION MARK, U+FE65 SMALL ANGLE BRACKET) which a regexp can grasp.

    Both mean nothing to PHP, but can have practical uses for PHP-unaware or semi-aware external toolkits. Again cat-joined scripts come to mind, with resulting // ? > <?php concatenations that inline-retain the former file sectioning.

So there are context-dependent but practical alternatives to an imperative close tag omission.

Manual babysitting of ?> close tags is not very contemporary either way. There always have been automation tools for that (even if just sed/awk or regex-oneliners). In particular:

phptags tag tidier

https://fossil.include-once.org/phptags/

Which could generally be used to --unclose php tags for third-party code, or rather just fix any (and all) actual whitespace/BOM issues:

  • phptags --warn --whitespace *.php

It also handles --long tag conversion etc. for runtime/configuration compatibility.

Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to security

Monitoring the Full Disclosure mailinglist Two Page Login with Spring Security 3.2.x How to prevent a browser from storing passwords JWT authentication for ASP.NET Web API How to use a client certificate to authenticate and authorize in a Web API Disable-web-security in Chrome 48+ When you use 'badidea' or 'thisisunsafe' to bypass a Chrome certificate/HSTS error, does it only apply for the current site? How does Content Security Policy (CSP) work? How to prevent Screen Capture in Android Default SecurityProtocol in .NET 4.5

Examples related to http-headers

Set cookies for cross origin requests Adding a HTTP header to the Angular HttpClient doesn't send the header, why? Passing headers with axios POST request What is HTTP "Host" header? CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response Using Axios GET with Authorization Header in React-Native App Axios get access to response header fields Custom header to HttpClient request Send multipart/form-data files with angular using $http Best HTTP Authorization header type for JWT