为什么要省略close标记?

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

现代版本的PHP在PHP .ini中设置了output_buffering标志 如果开启了输出缓冲,由于返回的代码不会立即发送到浏览器,可以在输出HTML后设置HTTP报头和cookie
每一本好的实践书籍和维基都以这个“规则”开始,但没有人提供好的理由。 还有其他好的理由跳过PHP结束标记吗?< / >强

128064 次浏览

这不是标签……

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

如果你把它作为一个包含在文档的顶部,你可能会在你试图发送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]

无效。

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

会的。

这一次,你必须懒得安全

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

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

对于你的问题

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

不,没有另一个跳过结束php标记的好理由。

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

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

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

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

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

如果你相信第二条路径,这为两种类型的.php文件打开了大门:

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

基于此,纯代码文件可以在没有?>结束标记的情况下结束。但是XML代码文件不能在没有?>关闭的情况下结束,因为这会使XML无效。

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

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

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

它是一个新手编码风格推荐,善意的,建议的通过手册

  • 然而,避免?>解决了只是一个涓流的常见头已经发送的原因(原始输出,BOM,通知等)及其后续问题。

  • PHP实际上包含了一些魔法来处理?>结束令牌之后的单个换行符。尽管这有历史问题,并且使新来者仍然容易受到松散的编辑器的影响,并且在?>之后无意识地在其他空白中移动。

  • 在风格上,一些开发人员更喜欢将<?php?>视为SGML标记/ XML处理指令,这意味着尾随关闭令牌的平衡一致性。(顺便说一下,对于依赖连接类来说是有用的可以取代低效的逐文件自动加载。)

  • 有点不寻常的是,开头<?php被描述为PHPs shebang(并且完全可行,每binfmt_misc),从而验证了相应的结束标记的冗余。

  • 经典PHP语法指南强制?>\n和更多的最近的(PSR-2)同意省略之间存在明显的建议差异 (郑重声明:Zend框架假设其中一种优于另一种并不意味着它固有的优越性。这是一种误解,认为专家被笨重的api吸引/目标受众)

  • SCMs和现代ide 提供内置解决方案主要减轻了近标记的照顾。

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

关闭标签的变化

  • regular ?>关闭标记也被称为T_CLOSE_TAG,或因此“关闭标记”。

  • 它包含了更多的化身,因为php的魔力换行符吃:

    ?比;<强> \ n < / >强 (Unix换行)

    ?比;<强> \ r < / >强(回车,经典mac)

    ?比;<强> \ r < / >强<强> \ n < / >强 (CR/LF,在DOS/Win)

    但是,PHP不支持Unicode组合换行符NEL (U+0085)。

    早期的PHP版本有IIRC编译程序在一定程度上限制了平台不可知论(FI甚至只是使用>作为关闭标记),这可能是关闭标记避免的历史起源

  • 经常被忽视,但直到PHP7移除它们,常规的<?php开放令牌可以有效与很少使用的</script>作为奇数关闭令牌

  • 硬结束标签”甚至不是一个——只是为了类比而创造了这个术语。然而,在概念上和用法上,__halt_compiler应该被识别为关闭令牌。

    __HALT_COMPILER();
    ?>
    

    它基本上让标记器丢弃任何代码或普通HTML部分。特别是PHAR存根使用它,或者如上所述,它与?>的冗余组合

  • 同样,void return;很少在include脚本中替换,导致任何带有尾随空格的?>无效。

  • 然后有各种各样的软/人造结束标记变体;不太为人所知,很少使用,但通常是根据没用令牌:

    • 简单的空格// ? >以逃避php标记器的检测。

    • 或者花哨的Unicode替代品// ﹖﹥ (U+FE56小问号,U+FE65小尖括号),这是regexp可以掌握的。

    都是对PHP毫无意义,但可以对php不感知或半感知的外部工具包有实际用途。再次想到__abc0连接脚本,产生的// ? > <?php连接内联保留了前文件部分

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

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

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

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

  • phptags --warn --whitespace *.php

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

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

程序员可以故意刷新缓冲区或输出缓冲区那么PHP中的输出缓冲区选项真的会改变结束标记对编码的影响吗?我认为不是这样的。

也许这就是为什么大多数答案都回到了个人风格和语法。

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

  1. 虽然当前的PHP版本可能有输出缓冲,但您将部署代码的实际生产服务器比任何开发或测试机器都重要得多。而且他们并不总是倾向于立即跟随最新的PHP趋势。

  2. 你可能会因为莫名其妙的<强>功能丧失而头痛。假设,您正在实现某种支付网关,并在支付处理程序成功确认后将用户重定向到特定的URL。如果出现某种PHP错误(甚至是警告),或者出现多行结束,则付款可能仍未处理,用户可能看起来仍未计费。这也是为什么不必要的重定向是邪恶的,如果要使用重定向,必须谨慎使用的原因之一。

  3. 即使在最新版本的ie浏览器中,您也可能会遇到“页面加载取消”类型的错误。这是因为AJAX response/json include包含了一些它不应该包含的内容,因为在一些PHP文件中有多余的行结束符,就像我几天前遇到的那样。

  4. 如果你的应用中有一些文件下载,它们也会因此而崩溃。你可能不会注意到它,即使在多年之后,因为特定的破坏下载习惯取决于服务器,浏览器,文件的类型和内容(可能还有其他一些我不想让你厌烦的因素)。

  5. 最后,许多PHP框架包括Symfony,< a href = " http://framework.zend.com/manual/1.10/en/coding-standard.php-file-formatting.html " rel = " noreferrer > Zend < / >和Laravel(没有提到这个< a href = " https://github.com/laravel/framework/blob/master/CONTRIBUTING.md #编码指南”rel = " noreferrer " >编码指南> < /但它遵循诉讼)和< a href = " http://www.php-fig.org/psr/psr-2/ " rel = " noreferrer > PSR-2标准< / >(2.2)项需要省略结束标签。PHP手册本身(< a href = " http://php.net/basic-syntax.instruction-separation " rel = " noreferrer " > < / >, < a href = " http://php.net/manual/en/language.basic-syntax.phptags.php " rel = " noreferrer > 2 < / >), < a href = " http://make.wordpress.org/core/handbook/coding-standards/php/ # remove-trailing-spaces”rel = " noreferrer " > Wordpress < / >, < a href = " https://www.drupal.org/coding-standards # phptags”rel = " noreferrer " > Drupal < / >和其他许多PHP软件我猜,建议这样做。如果您只是养成了遵循标准的习惯(并且为您的代码设置PHP-CS-Fixer),您可以忘记这个问题。否则,你就得一直把这个问题记在心里。

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

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

优点

缺点

结论

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

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

你不希望在生成二进制输出、CSV数据或其他非html输出时不经意地输出多余的空白字符。

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

在我们的生产机器上,当结束php标记后面有空白时,Apache 2.4.6与PHP 5.4实际上分割错误。我只是浪费了几个小时,直到我最终缩小了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一样。

  • 在某些情况下,您可能希望连接源。如果省略关闭?>标记而导致不一致,这将不像简单地执行cat source1.php source2.php那样容易。

  • 如果没有?>,就很难判断文档是否处于PHP转义模式或PHP忽略模式(PI标签<?php可能已经打开或没有打开)。如果您始终将文档保持在PHP忽略模式,那么生活会更容易一些。这就像使用格式良好的HTML文档与使用未关闭、嵌套糟糕的标记等的文档进行比较一样。

  • 似乎有些编辑器,如Dreamweaver可能有问题,PI left open [1]

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

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

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

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

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

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