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

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

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


这不是标签……

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

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


嗯,我知道原因,但我不能说出来:

对于只包含PHP代码的文件,永远不会出现结束标记(?>) 允许的。PHP并不要求它, 省略它可以防止 意外注入尾白 空格变成响应。

来源:http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html


不让结束语?>进入是非常有用的。

该文件对PHP是有效的(不是语法错误),正如@David Dorward所说,它允许避免在?>后面有空格/换行符(任何可以向浏览器发送头信息的东西)。

例如,

<?
    header("Content-type: image/png");
    $img = imagecreatetruecolor ( 10, 10);
    imagepng ( $img);
?>
[space here]
[break line here]

无效。

But

<?
    header("Content-type: image/png");
    $img = imagecreatetruecolor ( 10, 10 );
    imagepng ( $img );

会的。

就这一次,为了安全,你必须偷懒。


应该去掉php结束标记(?>)的原因是,这样程序员就不会意外地发送额外的换行字符。

不应该省略php结束标记的原因是它会导致php标记的不平衡,任何稍微有点头脑的程序员都可以记住不要添加额外的空白。

对于你的问题

还有其他好的理由跳过结束php标记吗?

不,没有其他好的理由跳过结束php标记。

我将以不使用结束标签的一些理由来结束:

人们总是会犯错误,不管他们有多聪明。 坚持一种可以减少可能错误数量的做法(恕我直言)是一个好主意。 PHP不是XML。PHP不需要遵循xml的严格标准来编写良好并具有良好的功能。如果一个丢失的结束标签让你烦恼,你可以使用一个结束标签,这不是一个固定不变的规则。


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

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代码…

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

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


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

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

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


如果我正确理解这个问题,它与输出缓冲以及这可能对结束/结束标记的影响有关。我不确定这是一个完全合理的问题。问题是输出缓冲区并不意味着所有内容在发送到客户机之前都保存在内存中。意思是有些内容是。

程序员可以故意刷新缓冲区或输出缓冲区那么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*)$替换为空文本。


Pros

像其他语言一样,关闭任何打开的标记是合乎逻辑的。不仅是X(HT)ML标签,还有花括号,括号… 对初学者来说更容易理解。

Cons

避免在结束标记后无意中添加空白,因为它破坏了header()函数的行为…一些编辑器或FTP客户端/服务器也会自动更改文件的结尾(至少,这是它们的默认配置) PHP手册说关闭标记是可选的,Zend甚至禁止它。

结论

我想说,支持省略标记的论点看起来更强(有助于避免header() +它是PHP/Zend的“推荐”)。我承认,就语法一致性而言,这不是我见过的最“漂亮”的解决方案,但还有什么更好的呢?


“是否有其他好的理由(除了标题问题)跳过结束php标记?”

在生成二进制输出、CSV数据或其他非html输出时,您不希望无意中输出无关的空白字符。


除了已经说过的所有内容之外,我还将提出另一个原因,这对我们的调试来说是一个巨大的痛苦。

Apache 2.4.6和php5.4实际上在我们的生产机器上,当关闭PHP标记后面有空白时,分割错误。我只是浪费了好几个小时,直到我终于用strace缩小了虫子的范围。

下面是Apache抛出的错误:

[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)

由于我的问题被标记为这个问题的重复,我认为可以发布为什么不省略结束标签?>可能是出于某些原因。

具有完整的处理指令语法(<?php……?>) PHP源代码是有效的SGML文档,可以用SGML解析器毫无问题地解析和处理。在附加的限制下,它也可以是有效的XML/XHTML。

没有什么可以阻止您编写有效的XML/HTML/SGML代码。PHP文档意识到了这一点。摘录:

注意:还要注意,如果要在XML或XHTML中嵌入PHP,则需要使用< ? PHP ?>标记以保持与标准兼容。

当然,PHP语法不是严格的SGML/XML/HTML,您创建的文档不是SGML/XML/HTML,就像您可以将HTML转换为XHTML以符合XML或不符合XML一样。

At some point you may want to concatenate sources. This will be not as easy as simply doing cat source1.php source2.php if you have inconsistency introduced by omitting closing ?> tags. Without ?> it's harder to tell if document was left in PHP escape mode or PHP ignore mode (PI tag <?php may have been opened or not). Life is easier if you consistently leave your documents in PHP ignore mode. It's just like work with well formatted HTML documents compared to documents with unclosed, badly nested tags etc. It seems that some editors like Dreamweaver may have problems with PI left open [1].


php代码有两种可能的用法:

PHP代码,如类定义或函数定义 使用PHP作为模板语言(例如在视图中)

在情形1中。关闭标签是完全没用的,我也想看到只有1(一个)php打开标签和NO(零)关闭标签在这种情况下。这是一个很好的实践,因为它使代码清晰,并将逻辑与表示分开。 对于表示情况(2.),有些人发现关闭所有标签(甚至是PHP处理的标签)是很自然的,这导致了混乱,因为PHP实际上有2个独立的用例,不应该混合在一起:逻辑/微积分和表示


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

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

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