PHP 闭合标签(closing tag)的使用问题和强烈建议

使用 PHP 脚本开发动态网站非常方便,只要在 HTML 页面内,嵌入由 PHP 开始标签()和闭合标签(?>)的 PHP 脚本即可;也可以作为 FastCGI 来使用。本文描述的就是一个单独的、纯粹的 .php 文件,处理闭合标签时遇到的一个问题。

  • php.net:official PHP resource;
  • php @ w3schools;
  • 关于 opening and closing tags
    A PHP script starts with and ends with ?>
问题缘起(使用 gtmetrix 改进性能时发现)
  • 每个 API 接口返回的都是 json;
  • 对于每个接口的处理,服务端虽然看起来同样的机制,大部分接口也是如愿返回 Content-Type:application/json,但仍有个别 API(如 r=city/list) 的 Response Header Content-Type:text/html
  • nginx 启用 gzip 后,发现有的接口内容少于1k,却仍然进行了压缩(所设 gzip_min_length 1k; 并未起作用);
解决过程简述
  • gzip 问题解决方案:需要 PHP 在返回 json 内容给 nginx 时加上 Content-Length: Header,由此才发现多了一个换行符(0x0a)(期间也是经过波折才发现返回的内容最前面多了一个换行符);
  • 在不同环境(开发、测试、生产)下的表现还不一样;在 scp 文件时发现了 components/Controller.php 文件末尾闭合标签 ?> 后多了一个换行符(0x0a);
  • r=city/list 接口返回的 json 内容比较多,echo 语句使用位置不当使得 PHP 分阶段发送内容给 nginx 引发 headers_sent,故导致 r=city/list 接口的 Response Header Content-Type:text/html(由 nginx 默认设定),而不是 PHP 意向设定的 application/json
  • r=city/list 接口和其他接口的中间处理逻辑还是有不一致的地方:echo 内容的地方不一致,内容大小数量级不同;
原因分析
  • 这个问题源于 PHP 对于闭合标签 ?> 的处理机制;与 HTML 代码混合编程时,PHP 引擎当然是不能随便处理空白字符的;而有的编辑器(vim)会自动在文件最后一行加个换行符(如果那一没有以换行符(0x0a)结束),这就导致在一个 .php 文件尾部(闭合标签之后) Appending 的一个换行符,PHP 会将之输出成了页面的一部分,即 http 回应的 body 头部 Prepending 了一个换行符;
  • 当 PHP echo 语句使用位置不当,且在返回内容超过一个 chunk 时,会使得 PHP 分阶段发送内容到 nginx,从而结束了 http header 部分的生成,你在这之后无法设置 header 了。
    换句话说,你应当 在设置 header之前不要输出任何内容:
    比如 echo 就是输出(尽管未必真输出);像文件末尾闭合标签 ?> 之后换行符这样的任何一个不经意的输出也是输出;
强烈建议
  • 所有的纯 .php 文件,一律不要再在文件结尾加闭合标签 ?> 了;API 服务就是一个纯粹的数据接口服务,没有 HTML 混合代码,所以 API 代码文件都不要加闭合标签;
  • vim 的设置:在 .vimrc 中,set binary 即可;就不会显示 [noeol] 了,也不会再在保存时加上换行符了;
闭合标签引起的问题表现汇总
  • XML 文件错误问题(早期:2009-2014 发生过);
    即:服务端生成的 .xml 文件,IE 不能识别问题,就是因为 文件开头多了一个换行符(0x0a),表现出来就是空了一行;
  • “Headers already sent” error in PHP;
  • API 接口返回的 json 内容前的空行问题;
vim 编辑器对文本文件行的处理
  • vim 编辑器对文本文件的每一行,都会 有一个行结束符(0x0a);
  • 你可以分别试一下 cat,echo,touch,vim 命令,他们 各有不同的表现;
  • git diff 常见现象


    PHP 闭合标签(closing tag)的使用问题和强烈建议_第1张图片
    一个文件,通过 vim 保存了一下,看起来什么都没修改,git status 发现有改变:就是在文件末尾加了一个换行符,原文件没这个换行符

你可能感兴趣的:(PHP 闭合标签(closing tag)的使用问题和强烈建议)