提问人:johnlemon 提问时间:12/11/2010 最后编辑:Mehranjohnlemon 更新时间:7/25/2019 访问量:131019
为什么要省略关闭标签?
Why would one omit the close tag?
问:
我一直在阅读在文件末尾使用 PHP close 标签是一种糟糕的做法。在以下上下文中,标头问题似乎无关紧要(这是迄今为止唯一好的论据):?>
PHP 的现代版本在 php.ini 中设置了 output_buffering 标志 如果启用了输出缓冲,则可以在输出 HTML 后设置 HTTP 标头和 cookie,因为返回的代码不会立即发送到浏览器。
每本好的实践书和维基都以这个“规则”开头,但没有人提供充分的理由。有没有其他很好的理由跳过结束的PHP标签?
答:
它不是一个标签......
但是,如果你拥有它,你就有可能在它后面有空格。
如果您随后将其用作文档顶部的包含,则在尝试发送 HTTP 标头之前,您最终可能会插入空格(即内容)......这是不允许的。
评论
<?php $i = 1; ?>
<?php include 'file1.php'; header('Location: http://www.google.com');?>
phpcs
好吧,我知道原因,但我无法表现出来:
对于仅包含 PHP 代码的文件,结束标记 () 从不 允许。PHP不需要它, 省略它会阻止 意外注入拖曳白色 空间进入响应。
?>
来源:http://framework.zend.com/manual/en/coding-standard.php-file-formatting.html
评论
不让关闭非常有用。?>
该文件对 PHP 保持有效(不是语法错误),正如 Dorward 所说@David它允许避免在 .?>
例如
<?
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 );
将。
这一次,你必须懒惰才能安全。
评论
?>
echo
?>
?>
您应该省略 php 结束标签 () 的原因是为了让程序员不会意外发送额外的换行符。?>
你不应该省略 php 结束标签的原因是因为它会导致 php 标签的不平衡,任何有一半想法的程序员都可以记住不要添加额外的空格。
所以对于你的问题:
有没有其他很好的理由跳过结尾的 php 标签?
不,没有其他很好的理由跳过结尾的 php 标签。
最后,我将提出一些不打扰结束标签的论据:
人们总是会犯错误,无论他们多么聪明。 坚持减少可能错误数量的做法(恕我直言)是个好主意。
PHP 不是 XML。PHP 不需要遵守 XML 的严格标准才能写得好且功能强大。如果缺少的结束标签让您感到恼火,您可以使用结束标签,这不是一个一成不变的规则。
评论
嗯,有两种看待它的方式。
- PHP代码只不过是一组XML处理指令,因此任何带有扩展名的文件都只不过是一个XML文件,恰好被解析为PHP代码。
.php
- PHP 恰好共享其 open 和 close 标签的 XML 处理指令格式。基于此,扩展名的文件可能是有效的 XML 文件,但不一定是。
.php
如果您相信第一种路由,那么所有 PHP 文件都需要结束标记。省略它们将创建一个无效的 XML 文件。话又说回来,如果没有打开声明,你无论如何都不会有一个有效的XML文件......所以这不是一个大问题......<?xml version="1.0" charset="latin-1" ?>
如果您相信第二种途径,这将为两种类型的文件打开大门:.php
- 仅包含代码的文件(例如库文件)
- 包含本机 XML 和代码的文件(例如模板文件)
基于此,纯代码文件可以在没有结束标记的情况下结束。但是XML代码文件不能在没有关闭的情况下结束,因为它会使XML无效。?>
?>
但我知道你在想什么。你在想这有什么关系,你永远不会直接渲染一个PHP文件,所以谁在乎它是否是有效的XML。好吧,如果您正在设计模板,这确实很重要。如果它是有效的 XML/HTML,普通浏览器将根本不显示 PHP 代码(它被视为注释)。因此,您可以模拟模板,而无需在其中运行PHP代码。
我并不是说这很重要。这只是一个我不经常看到表达的观点,所以还有什么更好的地方来分享它......
就个人而言,我不会关闭库文件中的标签,而是在模板文件中关闭......我认为这是基于个人偏好(和编码指南)的,而不是任何困难......
评论
这是一个新手编码风格的建议,用心良苦,并由手册建议。
然而,避免只解决了已经发送的常见标头原因(原始输出、BOM、通知等)及其后续问题的一小部分。
?>
PHP实际上包含一些魔力,可以在关闭令牌之后吃掉单个换行符。尽管这存在历史问题,并且使新人仍然容易受到不稳定的编辑的影响,并在之后不知不觉地在其他空白中洗牌。
?>
?>
从风格上讲,一些开发人员更喜欢查看 和 作为 SGML 标签/XML 处理指令,这意味着尾随收盘标记的余额一致性。(顺便说一句,对于依赖连接类来说很有用,可以取代低效的逐个文件自动加载。
<?php
?>
有点罕见的是,开口被描述为 PHPs shebang(并且完全可行,每binfmt_misc),从而验证了相应关闭标签的冗余。
<?php
在经典的PHP语法指南和最近的PHP语法指南(PSR-2)之间有一个明显的建议差异。
(郑重声明:Zend Framework 假设一个优于另一个并不意味着它固有的优越性。这是一种误解,认为专家被笨拙的 API 所吸引/目标受众)。?>\n
劝阻任何关闭标签的使用只会延迟解释基本的 PHP 处理行为和语言语义,以避免不常见的问题。由于参与者的熟练程度差异,协作软件开发仍然是实用的。?>
关闭标签变体
常规关闭标记也称为
T_CLOSE_TAG
,或因此称为“关闭标记”。?>它包含更多的化身,因为 PHP 的神奇换行符饮食:
?>\n(Unix 换行)
?>\r(回车,经典 MAC)
?>\r\n(CR/LF,在 DOS/Win 上)
但是,PHP 不支持 Unicode 组合换行符 (U+0085)。NEL
早期的PHP版本有IIRC编译,在一定程度上限制了平台不可知论(FI甚至只是用作关闭标记),这可能是关闭标记避免的历史起源。
>
经常被忽视,但在 PHP7 删除它们之前,常规的开局代币可以与很少用作奇数的收盘代币有效配对。
<?php
</script>
“硬关闭标签”甚至不是一个 - 只是为了类比而编造了这个术语。然而,从概念和用法上讲
,__halt_compiler
应该被认为是接近的标记。__HALT_COMPILER(); ?>
这基本上让分词器此后丢弃任何代码或纯 HTML 部分。特别是,PHAR 存根利用了它,或者它与所描述的冗余组合。
?>
void
返回也是如此;
很少在包含脚本中替换,使任何带有尾随空格的脚本无效。?>
然后是各种软/假关闭标签变体;鲜为人知且很少使用,但通常每个注释掉的标记:
简单的间距,以逃避PHP分词器的检测。
// ? >
或者花哨的 Unicode 替代品(U+FE56 小问号,U+FE65 小尖括号),正则表达式可以掌握。
// ﹖﹥
两者对PHP来说都毫无意义,但对于PHP无感知或半感知的外部工具包来说,它们都有实际用途。再次联接脚本浮现在脑海中,其生成的串联将内联保留以前的文件部分。
cat
// ? > <?php
因此,对于命令式关闭标签省略,有一些依赖于上下文但实用的替代方法。
无论哪种方式,贴标签的手动保姆都不是很现代。一直有自动化工具(即使只是 sed/awk 或正则表达式)。特别:?>
phptags 标记 tidier
https://fossil.include-once.org/phptags/
这通常可用于第三方代码的php标签,或者更确切地说,只是修复任何(和所有)实际的空格/ BOM问题:--unclose
phptags --warn --whitespace *.php
它还处理标签转换等,以实现运行时/配置兼容性。--long
评论
<?php if($var): ?>Hello World<?php endif; ?>
如果我正确理解了这个问题,它与输出缓冲以及这可能对关闭/结束标签产生的影响有关。我不确定这是一个完全有效的问题。问题在于,输出缓冲区并不意味着所有内容在发送到客户端之前都保存在内存中。这意味着某些内容是。
程序员可以故意刷新缓冲区或输出缓冲区,那么 PHP 中的输出缓冲区选项真的会改变结束标签对编码的影响吗?我认为事实并非如此。
也许这就是为什么大多数答案都回到了个人风格和语法上。
在正常课程之前发送标头可能会产生深远的后果。以下是我目前碰巧想到的几个:
虽然当前的 PHP 版本可能具有输出缓冲功能,但您将部署代码的实际生产服务器远比任何开发或测试机器都重要得多。而且他们并不总是倾向于立即遵循最新的PHP趋势。
您可能会因莫名其妙的功能丢失而头疼。假设您正在实施某种支付网关,并在支付处理器成功确认后将用户重定向到特定 URL。如果发生某种 PHP 错误,甚至警告或多行结尾,付款可能仍未处理,用户可能仍未计费。这也是为什么不必要的重定向是邪恶的原因之一,如果要使用重定向,必须谨慎使用。
您可能会在 Internet Explorer 中收到“页面加载已取消”类型的错误,即使在最新版本中也是如此。这是因为 AJAX 响应/json 包含它不应该包含的内容,因为某些 PHP 文件中的行尾过多,就像我几天前遇到的那样。
如果您的应用程序中有一些文件下载,它们也可能会因此而中断。即使多年后,您也可能不会注意到它,因为下载的具体破坏习惯取决于服务器、浏览器、文件的类型和内容(可能还有其他一些我不想让您感到厌烦的因素)。
最后,许多 PHP 框架,包括 Symfony、Zend 和 Laravel(在编码指南中没有提到这一点,但它遵循了相应内容)和 PSR-2 标准(第 2.2 项)都要求省略结束标记。PHP手册本身(1,2),Wordpress,Drupal和许多其他PHP软件,我猜,建议这样做。如果您只是养成遵循标准的习惯(并为您的代码设置 PHP-CS-Fixer),您可以忘记这个问题。否则,您将始终需要牢记这个问题。
奖励:与这 2 个角色相关的一些陷阱(实际上是目前一个):
- 甚至一些知名的库也可能包含过多的行尾。一个例子是 Smarty,即使是最新版本的 2.* 和 3.* 分支也有这个。因此,一如既往,请注意第三方代码。奖励中的奖励:用于删除不必要的PHP结尾的正则表达式:将包含PHP代码的所有文件中的空文本替换。
?>
(\s*\?>\s*)$
评论
\?>(?s:.){0,10}\Z
?>
?> Hello
<?php echo "test"; ?> Hello
[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)
?>
<header>
优点
- 关闭任何打开的标签是合乎逻辑的,就像使用其他语言一样。不仅是 X(HT)ML 标签,还有大括号、括号......
- 对于初学者来说不那么令人困惑。
缺点
- 避免了在结束标签后无意中添加空格的麻烦,因为它破坏了 header() 函数行为......一些编辑器或FTP客户端/服务器也会自动更改文件的结尾(至少,这是它们的默认配置)
- PHP手册说结束标签是可选的,Zend甚至禁止它。
结论
我想说的是,支持省略标签的论点看起来更强大(有助于避免 header() + 它是 PHP/Zend“推荐”的大麻烦)。我承认,就语法一致性而言,这不是我见过的最“漂亮”的解决方案,但还有什么比这更好的呢?
“除了标头问题之外,还有其他很好的理由跳过结束的php标签吗?”
您不希望在生成二进制输出、CSV 数据或其他非 HTML 输出时无意中输出无关的 whitepace 字符。
评论
除了已经说过的所有内容之外,我还将抛出另一个原因,这对我们来说是一个巨大的痛苦。
Apache 2.4.6 和 PHP 5.4 实际上,当结束标记后面有空空间时,我们的生产机器上会分段错误。我只是浪费了几个小时,直到我最终用 strace 缩小了错误范围。php
这是Apache抛出的错误:
[core:notice] [pid 7842] AH00052: child pid 10218 exit signal Segmentation fault (11)
由于我的问题被标记为与此问题重复,我认为可以发布为什么出于某些原因不省略结束标签是可以的。?>
- 具有完整的处理指令语法 () PHP 源是有效的 SGML 文档,可以使用 SGML 解析器进行解析和处理而不会出现问题。有其他限制,它也可以是有效的 XML/XHTML。
<?php ... ?>
没有什么能阻止您编写有效的 XML/HTML/SGML 代码。PHP文档已经意识到了这一点。摘录:
注意:另请注意,如果要在 XML 或 XHTML 中嵌入 PHP,则需要使用 < ?php ?> 标记以保持符合标准。
当然,PHP语法不是严格的SGML/XML/HTML,你创建一个文档,它不是SGML/XML/HTML,就像你可以把HTML变成XHTML是否符合XML一样。
在某些时候,您可能希望连接源。如果您通过省略结束标记引入不一致,这将不像简单地这样做那么容易。
cat source1.php source2.php
?>
如果没有,就很难判断文档是处于PHP转义模式还是PHP忽略模式(PI标签可能已打开)。如果您始终将文档保持在 PHP 忽略模式,生活会更轻松。这就像使用格式良好的 HTML 文档与具有未关闭、嵌套不良的标签等的文档相比。
?>
<?php
似乎像 Dreamweaver 这样的一些编辑器可能存在 PI 未打开的问题 [1]。
php 代码有 2 种可能的用途:
- PHP代码,如类定义或函数定义
- 使用 PHP 作为模板语言(即在视图中)
在案例 1.结束标签是完全没有用的,在这种情况下,我也希望看到只有 1(一)个 php 打开标签和 NO(零)结束标签。这是一个很好的做法,因为它使代码干净并将逻辑与表示分开。 对于表示案例(2.),一些人发现关闭所有标签(甚至是PHP处理的标签)是很自然的,这导致了混淆,因为PHP实际上有2个单独的用例,不应该混淆:逻辑/微积分和表示
根据文档,如果结束标记位于文件末尾,则最好省略它,原因如下:
如果文件是纯 PHP 代码,则最好省略文件末尾的 PHP 结束标记。这样可以防止在 PHP 结束标记后意外添加空格或新行,这可能会导致不良影响,因为当程序员无意在脚本中的该点发送任何输出时,PHP 将启动输出缓冲。
评论
?>