php 为什么要省略关闭标签?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4410704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 12:58:37  来源:igfitidea点击:

Why would one omit the close tag?

phpsecurityhttp-headers

提问by danidacar

I keep reading it is poor practice to use the PHP close tag ?>at the end of the file. The header problem seems irrelevant in the following context (and this is the only good argument so far):

我一直在阅读?>在文件末尾使用 PHP 结束标记是一种不好的做法。标题问题在以下上下文中似乎无关紧要(这是迄今为止唯一的好论点):

Modern versions of PHP set the output_buffering flag in php.ini If output buffering is enabled, you can set HTTP headers and cookies after outputting HTML because the returned code is not sent to the browser immediately.

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

Every good practice book and wiki starts with this 'rule' but nobody offers good reasons. Is there another good reason to skip the ending PHP tag?

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

采纳答案by Halil ?zgür

Sending headers earlier than the normal course may have far reaching consequences. Below are just a few of them that happened to come to my mind at the moment:

比正常课程更早发送标头可能会产生深远的影响。以下是我目前想到的几个:

  1. While current PHP releases may have output buffering on, the actual production serversyou 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.

  2. 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.

  3. You may get "Page loading canceled" type of errors in Internet Explorer, even in the most recent versions. This is because an AJAXresponse/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.

  4. If you have some file downloadsin 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).

  5. Finally, many PHP frameworks including Symfony, Zendand Laravel (there is no mention of this in the coding guidelinesbut it follows the suit) and the PSR-2 standard(item 2.2) require omission of the closing tag. PHP manual itself (1,2), Wordpress, Drupaland many other PHP software I guess, advise to do so. If you simply make a habit of following the standard (and setup PHP-CS-Fixerfor your code) you can forget the issue. Otherwise you will always need to keep the issue in your mind.

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

  2. 您可能对莫名其妙的功能损失感到头疼。假设您正在实施某种支付网关,并在支付处理器成功确认后将用户重定向到特定 URL。如果发生某种 PHP 错误,甚至是警告或多余的行结束,付款可能仍未处理,用户可能看起来仍然没有收到帐单。这也是不必要的重定向是邪恶的原因之一,如果要使用重定向,必须谨慎使用。

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

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

  5. 最后,许多 PHP 框架,包括SymfonyZend和 Laravel(在编码指南中没有提到这一点,但它遵循诉讼)和PSR-2 标准(第 2.2 项)要求省略结束标记。PHP手册本身(12),WordPress的Drupal的和许多其他PHP软件我想,提醒这样做。如果您只是养成遵循标准的习惯(并为您的代码设置PHP-CS-Fixer),您可能会忘记这个问题。否则,您将始终需要牢记这个问题。

Bonus: a few gotchas (actually currently one) related to these 2 characters:

奖励:与这两个角色相关的一些问题(实际上目前是一个):

  1. Even some well-known libraries may contain excess line endings after ?>. An example is Smarty, even the most recent versions of both 2.* and 3.* branch have this. So, as always, watch for third party code. Bonus in bonus: A regex for deleting needless PHP endings: replace (\s*\?>\s*)$with empty text in all files that contain PHP code.
  1. 甚至一些著名的库也可能在?>. 一个例子是 Smarty,即使是 2.* 和 3.* 分支的最新版本也有这个。因此,与往常一样,请注意第三方代码。奖金奖励:用于删除不必要的 PHP 结尾的正则表达式:(\s*\?>\s*)$在所有包含 PHP 代码的文件中替换为空文本。

回答by zzzzBov

The reason you should leave off the php closing tag (?>) is so that the programmer doesn't accidentally send extra newline chars.

您应该?>省略php 结束标记 ( ) 的原因是程序员不会意外发送额外的换行符。

The reason you shouldn't leave off the php closing tag is because it causes an imbalance in the php tags and any programmer with half a mind can remember to not add extra white-space.

你不应该去掉 php 结束标签的原因是因为它会导致 php 标签的不平衡,任何有心的程序员都可以记住不要添加额外的空格。

So for your question:

所以对于你的问题:

Is there another good reason to skip the ending php tag?

还有另一个很好的理由跳过结尾的 php 标签吗?

No, there isn't anothergood reason to skip the ending php tags.

不,没有另一个很好的理由跳过结尾的 php 标签。

I will finish with some arguments for not bothering with the closing tag:

我将用一些不打扰结束标签的论据来结束:

  1. People are always able to make mistakes, no matter how smart they are. Adhering to a practice that reduces the number of possible mistakes is (IMHO) a good idea.

  2. PHP is not XML. PHP doesn't need to adhere to XMLs strict standards to be well written and functional. If a missing closing tag annoys you, you're allowed to use a closing tag, it's not a set-in-stone rule one way or the other.

  1. 人总是会犯错,不管他们多么聪明。坚持减少可能错误数量的做法是(恕我直言)一个好主意。

  2. PHP 不是 XML。PHP 不需要遵守 XML 的严格标准即可编写良好且功能强大。如果缺少的结束标签让您感到烦恼,您可以使用结束标签,这不是一种固定的规则。

回答by mario

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

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

  • Eschewing ?>however solves just a trickleof 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 <?phpand ?>as SGML tags / XML processing instructions, implying the balance consistency of a trailing close token. (Which btw, is usefulfor dependency-conjoining class includes to supplant inefficient file-by-file autoloading.)

  • Somewhat uncommonly the opening <?phpis 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 guidesmandating ?>\nand 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).

  • SCMsand modern IDEs provide builtin solutionsmostly alleviating close tag caretaking.

  • 避开?>但是只是解决了涓涓细流共同的已经发送的原因标题(原始输出,BOM,通知等)及其后续问题。

  • PHP 实际上包含一些魔法来在?>结束标记之后吃掉单个换行符。尽管这存在历史问题,并且让新人仍然容易受到不稳定的编辑器的影响,并且在?>.

  • 在风格上,一些开发人员更喜欢将<?php?>视为 SGML 标记/XML 处理指令,暗示尾随关闭令牌的余额一致性。(顺便说一句,这对于依赖连接类包括替代低效的逐文件自动加载很有用。)

  • 有点不常见的<?php是,开头的特征是 PHP 的shebang(并且每个binfmt_misc完全可行),从而验证相应关闭标签的冗余。

  • 强制执行的经典 PHP 语法指南?>\n与同意省略的最新版本 (PSR-2)之间存在明显的建议差异。
    (郑重声明:Zend Framework 假设两者之间存在差异并不意味着其固有的优越性。专家被吸引到/针对笨拙的 API 的目标受众是一种误解)。

  • SCM和现代 IDE提供了内置解决方案,主要是减轻关闭标签的管理。

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

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

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 <?phpopening token can be validlypaired 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_compilershould 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 / fauxclose tag variations; lesser known and seldomly used, but usually per commented-outtokens:

    • 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 // ? > <?phpconcatenations that inline-retain the former file sectioning.

  • 定期?>密切标签也被称为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 存根利用了它,或者它的冗余组合,?>如图所示。

  • 同样,在包含脚本中,voidreturn;很少被替换,从而使任何?>带有尾随空格的内容都无效。

  • 然后是各种软/人造封闭标签变体;鲜为人知且很少使用,但通常每个注释掉的标记:

    • // ? >逃避 PHP 标记器检测的简单间距。

    • 或者正则// ﹖﹥表达式可以掌握的花哨的Unicode替代品(U+FE56小问号,U+FE65小角括号)。

    两者对 PHP没有任何意义,但可以实际用于不支持 PHP 或半感知的外部工具包。再次cat想到 -joined 脚本,结果// ? > <?php串联,内联保留以前的文件分段。

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:

?>无论哪种方式,手动照看关闭标签都不是很现代。总是有自动化工具(即使只是 sed/awk 或 regex-oneliners)。特别是:

phptags tag tidier

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

phptags 标签更整洁

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

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

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

  • phptags --warn --whitespace *.php
  • phptags --warn --whitespace *.php

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

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

回答by Quentin

It isn't a tag…

这不是标签……

But if you have it, you risk having white space after it.

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

If you then use it as an include at the top of a document, you could end up inserting white space (i.e. content) before you attempt to send HTTP headers … which isn't allowed.

如果随后将其用作文档顶部的包含,则可能会在尝试发送 HTTP 标头之前插入空白(即内容)……这是不允许的。

回答by Shikiryu

It's pretty useful not to let the closing ?>in.

不让关闭?>进入非常有用。

The file stays valid to PHP (not a syntax error) and as @David Dorward said it allows to avoid having white space / break-line (anything that can send a header to the browser) after the ?>.

该文件对 PHP 保持有效(不是语法错误),正如@David Dorward 所说,它允许避免在?>.

For example,

例如,

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

won't be valid.

将无效。

But

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

will.

将要。

For once, you must be lazy to be secure.

这一次,您必须懒惰才能确保安全

回答by Asaph

According to the docs, it's preferable to omit the closing tag if it's at the end of the file for the following reason:

根据docs,如果它位于文件末尾,则最好省略结束标记,原因如下:

If a file is pure PHP code, it is preferable to omit the PHP closing tag at the end of the file. This prevents accidental whitespace or new lines being added after the PHP closing tag, which may cause unwanted effects because PHP will start output buffering when there is no intention from the programmer to send any output at that point in the script.

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

PHP Manual > Language Reference > Basic syntax > PHP tags

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

回答by tawfekov

Well, I know the reason, but I can't show it:

嗯,我知道原因,但我不能显示它:

For files that contain only PHP code, the closing tag (?>) is never permitted. It is not required by PHP, and omitting it prevents the accidental injection of trailing white space into the response.

对于仅包含 PHP 代码的文件,?>永远不允许使用结束标记 ( )。PHP 不需要它,省略它可以防止意外将尾随空白注入响应。

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

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

回答by ircmaxell

Well, there are two ways of looking at it.

好吧,有两种看待它的方式。

  1. PHP code is nothing more than a set of XML processing instructions, and therefore any file with a .phpextension is nothing more than an XML file that just so happens to be parsed for PHP code.
  2. PHP just so happens to share the XML processing instruction format for its open and close tags. Based on that, files with .phpextensions MAY be valid XML files, but they don't need to be.
  1. PHP 代码只不过是一组XML 处理指令,因此任何带有.php扩展名的文件只不过是一个 XML 文件,恰好被解析为 PHP 代码。
  2. PHP 恰好共享其打开和关闭标记的 XML 处理指令格式。基于此,具有.php扩展名的文件可能是有效的 XML 文件,但它们并非必须如此。

If you believe the first route, then all PHP files require closing end tags. To omit them will create an invalid XML file. Then again, without having an opening <?xml version="1.0" charset="latin-1" ?>declaration, you won't have a valid XML file anyway... So it's not a major issue...

如果您相信第一条路线,那么所有 PHP 文件都需要结束标记。省略它们将创建无效的 XML 文件。再说一次,如果没有开始<?xml version="1.0" charset="latin-1" ?>声明,无论如何你都不会拥有有效的 XML 文件......所以这不是一个主要问题......

If you believe the second route, that opens the door for two types of .phpfiles:

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

  • Files that contain only code (library files for example)
  • Files that contain native XML and also code (template files for example)
  • 仅包含代码的文件(例如库文件)
  • 包含原生 XML 和代码的文件(例如模板文件)

Based on that, code-only files are OK to end without a closing ?>tag. But the XML-code files are not OK to end without a closing ?>since it would invalidate the XML.

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

But I know what you're thinking. You're thinking what does it matter, you're never going to render a PHP file directly, so who cares if it's valid XML. Well, it does matter if you're designing a template. If it's valid XML/HTML, a normal browser will simply not display the PHP code (it's treated like a comment). So you can mock out the template without needing to run the PHP code within...

但我知道你在想什么。你在想这有什么关系,你永远不会直接渲染一个 PHP 文件,所以谁在乎它是否是有效的 XML。好吧,如果您正在设计模板,这很重要。如果它是有效的 XML/HTML,普通浏览器将不会显示 PHP 代码(它被视为注释)。因此,您可以模拟模板,而无需在其中运行 PHP 代码...

I'm not saying this is important. It's just a view that I don't see expressed too often, so what better place to share it...

我不是说这很重要。这只是一种我很少看到表达的观点,所以有什么更好的地方来分享它......

Personally, I do not close tags in library files, but do in template files... I think it's a personal preference (and coding guideline) based more than anything hard...

就我个人而言,我不会在库文件中关闭标签,而是在模板文件中关闭标签......我认为这是基于个人偏好(和编码指南)的比任何困难......

回答by Artem Russakovskii

In addition to everything that's been said already, I'm going to throw in another reason that was a huge pain for us to debug.

除了已经说过的所有内容之外,我还要提出另一个对我们调试来说非常痛苦的原因。

Apache2.4.6 with PHP 5.4 actually segmentation faults on our production machines when there's empty space behind the closing phptag. I just wasted hours until I finally narrowed down the bug with strace.

当结束php标签后面有空白空间时,Apache2.4.6 和 PHP 5.4 实际上会在我们的生产机器上出现分段错误。我只是浪费了几个小时,直到我最终用strace缩小了错误范围。

Here is the error that Apache throws:

这是Apache抛出的错误:

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

回答by user1238364

"Is there another good reason (other than the header problem) to skip the ending php tag?"

“还有另一个很好的理由(除了标题问题)跳过结尾的 php 标签吗?”

You don't want to inadvertently output extraneous whitepace characters when generating binary output, CSVdata, or other non-HTML output.

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