我一直在读,在文件末尾使用PHP关闭标记?>是不好的做法。在下面的上下文中,头文件的问题似乎无关紧要(这是目前为止唯一一个好的参数):

现代版本的PHP在PHP .ini中设置了output_buffering标志 如果启用了输出缓冲,则可以在输出HTML后设置HTTP报头和cookie,因为返回的代码不会立即发送到浏览器。

每一本好的实践书籍和维基都以这个“规则”开始,但没有人提供好的理由。 还有其他好的理由跳过PHP结束标记吗?


当前回答

嗯,有两种方式来看待它。

PHP代码只不过是一组XML处理指令,因此任何具有. PHP扩展名的文件都只不过是一个恰好被解析为PHP代码的XML文件。 PHP恰好为它的打开和关闭标记共享XML处理指令格式。基于此,扩展名为.php的文件可能是有效的XML文件,但它们不一定是。

如果您相信第一种方法,那么所有PHP文件都需要结束标记。省略它们将创建一个无效的XML文件。然后,没有开口<?xml version="1.0" charset="latin-1" ?>声明,你将不会有一个有效的xml文件…所以这不是一个大问题……

如果你相信第二种方法,那么就会出现两种类型的.php文件:

只包含代码的文件(例如库文件) 包含原生XML和代码的文件(例如模板文件)

基于此,只有代码的文件可以在没有?>结束标记的情况下结束。但是XML代码文件不使用?>结束是不合适的,因为它会使XML无效。

但我知道你在想什么。你会想,这有什么关系,你永远不会直接呈现PHP文件,所以谁会关心它是否是有效的XML。如果您正在设计一个模板,那么这确实很重要。如果它是有效的XML/HTML,普通浏览器将不会显示PHP代码(它被视为注释)。所以你可以模拟出模板,而不需要运行PHP代码…

我不是说这很重要。这只是一个我不经常看到的观点,所以还有什么更好的地方来分享它呢?

就我个人而言,我不关闭库文件中的标签,但在模板文件中这样做…我认为这是基于个人喜好(和编码指南)的。

其他回答

嗯,有两种方式来看待它。

PHP代码只不过是一组XML处理指令,因此任何具有. PHP扩展名的文件都只不过是一个恰好被解析为PHP代码的XML文件。 PHP恰好为它的打开和关闭标记共享XML处理指令格式。基于此,扩展名为.php的文件可能是有效的XML文件,但它们不一定是。

如果您相信第一种方法,那么所有PHP文件都需要结束标记。省略它们将创建一个无效的XML文件。然后,没有开口<?xml version="1.0" charset="latin-1" ?>声明,你将不会有一个有效的xml文件…所以这不是一个大问题……

如果你相信第二种方法,那么就会出现两种类型的.php文件:

只包含代码的文件(例如库文件) 包含原生XML和代码的文件(例如模板文件)

基于此,只有代码的文件可以在没有?>结束标记的情况下结束。但是XML代码文件不使用?>结束是不合适的,因为它会使XML无效。

但我知道你在想什么。你会想,这有什么关系,你永远不会直接呈现PHP文件,所以谁会关心它是否是有效的XML。如果您正在设计一个模板,那么这确实很重要。如果它是有效的XML/HTML,普通浏览器将不会显示PHP代码(它被视为注释)。所以你可以模拟出模板,而不需要运行PHP代码…

我不是说这很重要。这只是一个我不经常看到的观点,所以还有什么更好的地方来分享它呢?

就我个人而言,我不关闭库文件中的标签,但在模板文件中这样做…我认为这是基于个人喜好(和编码指南)的。

根据文档,如果关闭标记位于文件末尾,出于以下原因,最好省略它:

如果文件是纯PHP代码,最好省略文件末尾的PHP结束标记。这可以防止在PHP结束标记之后意外地添加空白或新行,这可能会导致不必要的影响,因为当程序员在脚本中不打算发送任何输出时,PHP将启动输出缓冲。

PHP手册>语言参考>基本语法> PHP标签

这不是标签……

但如果你有了它,你就有可能在它后面留下空白。

如果你把它作为一个包含在文档的顶部,你可能会在你试图发送HTTP头之前插入空白(即内容),这是不允许的。

这是一个新手编码风格的建议,出于善意,并由手册建议。

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.

不鼓励使用?>结束标记只是延迟解释基本的PHP处理行为和语言语义,以避免不常见的问题。由于参与者的熟练程度不同,它对于协作软件开发仍然是实用的。

关闭标签的变化

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.

因此,对于强制的关闭标记省略,有依赖于上下文但实用的替代方法。

手动照看?>结束标记也不是很现代。一直都有自动化工具(即使只有sed/awk或regex-oneliners)。特别是:

Phptags标签更整洁 https://fossil.include-once.org/phptags/

通常可以用来为第三方代码打开php标签,或者只是修复任何(和所有)实际的空白/BOM问题:

Phptags——warn——whitespace *.php

它还处理——长标签转换等运行时/配置兼容性。

比正常进程更早地发送头文件可能会产生深远的后果。下面是我当时碰巧想到的其中一些:

While current PHP releases may have output buffering on, the actual production servers you will be deploying your code on are far more important than any development or testing machines. And they do not always tend to follow latest PHP trends immediately. You may have headaches over inexplicable functionality loss. Say, you are implementing some kind payment gateway, and redirect user to a specific URL after successful confirmation by the payment processor. If some kind of PHP error, even a warning, or an excess line ending happens, the payment may remain unprocessed and the user may still seem unbilled. This is also one of the reasons why needless redirection is evil and if redirection is to be used, it must be used with caution. You may get "Page loading canceled" type of errors in Internet Explorer, even in the most recent versions. This is because an AJAX response/json include contains something that it shouldn't contain, because of the excess line endings in some PHP files, just as I've encountered a few days ago. If you have some file downloads in your app, they can break too, because of this. And you may not notice it, even after years, since the specific breaking habit of a download depends on the server, the browser, the type and content of the file (and possibly some other factors I don't want to bore you with). Finally, many PHP frameworks including Symfony, Zend and Laravel (there is no mention of this in the coding guidelines but it follows the suit) and the PSR-2 standard (item 2.2) require omission of the closing tag. PHP manual itself (1,2), Wordpress, Drupal and many other PHP software I guess, advise to do so. If you simply make a habit of following the standard (and setup PHP-CS-Fixer for your code) you can forget the issue. Otherwise you will always need to keep the issue in your mind.

额外的:一些与这两个角色有关的陷阱(实际上目前只有一个):

甚至一些知名的库可能在?>之后包含多余的行尾。一个例子是Smarty,甚至是这两个版本的最新版本。*和3。*分支有这个。因此,与往常一样,要注意第三方代码。额外的奖励:一个用于删除不必要的PHP结尾的正则表达式:在所有包含PHP代码的文件中将(\s*\?>\s*)$替换为空文本。