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

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

  • php.net:official PHP resource;
  • php @ w3schools
  • 关于 opening and closing tags
    A PHP script starts with <?php 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] 了,也不会再在保存时加上换行符了;
闭合标签引起的问题表现汇总
vim 编辑器对文本文件行的处理
  • vim 编辑器对文本文件的每一行,都会 有一个行结束符(0x0a)
  • 你可以分别试一下 cat,echo,touch,vim 命令,他们 各有不同的表现
  • git diff 常见现象


    一个文件,通过 vim 保存了一下,看起来什么都没修改,git status 发现有改变:就是在文件末尾加了一个换行符,原文件没这个换行符
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,837评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,833评论 25 708
  • PHP 学习目录 ├─PHP视频教程 1 LAMP网站构建 │ ├─PHP教程 1.1.1 新版视频形式介绍│ ...
    曹渊说创业阅读 16,175评论 29 417
  • 我渴望 推开窗就能看到一片海 那么多个月光柔柔的夜晚 海就守在我的窗前 守护着我为数不多的梦想 海风吹过窗台 惊扰...
    紫翼i阅读 182评论 0 3
  • 十九是每个人都有的。十九岁,有的人在读书,有的人结婚了!我的十九岁让我明白了人生不是想象中的那样一帆风顺。高考失...
    南桥南山阅读 306评论 0 0