ob_gzhandler需在输出前注册,仅对支持类型且客户端声明Accept-Encoding时压缩;优先级低于Web服务器压缩,冲突易致双重压缩或失效;调试须检查请求头、缓冲状态及中间层干扰。
PHP 输出前手动触发 gzip 压缩(
的实际用法)
PHP 本身不自动压缩响应体,得靠输出缓冲和 zlib 模块配合。最直接的方式是用
作为回调注册到
,但它不是“开了就压缩”,而是按需协商:只在客户端声明支持
且内容类型适合时才生效。
必须在任何输出(包括空格、BOM、
)之前调用,否则会报
它只压缩
、
、
等可压缩类型,对图片、PDF 等二进制响应无效
如果 Apache/Nginx 已启用全局 gzip,再用
可能导致双重压缩或
错误头
示例:
Apache + PHP 混合配置下,gzip 由谁控制?
常见混乱点:PHP 开了
,但 Apache 的
也在运行,结果响应头出现
却没压缩,或者压缩两次失败。
优先级:Apache/Nginx 的 Web 服务器层压缩 > PHP 的
>
PHP 的
是全局开关,开启后所有响应(含图片、下载文件)都尝试压缩,容易出错;建议关掉,改用更可控的
确认是否生效,别只看响应头
,还要用
实测响应大小变化
为什么用了
还没压缩?检查这三处
不是代码写了就一定压缩,关键在运行时环境与协商细节。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
客户端请求头没带
—— 浏览器禁用压缩、curl 默认不发、CDN 中间层剥离了该头
PHP 输出缓冲被提前启动,比如框架(Laravel、ThinkPHP)已调用
,再调
会失败,需检查
响应内容太小(默认阈值约 20B),zlib 认为压缩反而膨胀,直接跳过;可临时加长内容测试,如
Nginx 下 PHP-FPM 场景,gzip 配置必须分两层看
Nginx 不会自动把 PHP 的压缩逻辑透传出去,它只管自己配的
指令,而 PHP-FPM 的响应是 Nginx 当作普通 body 处理的。
Nginx 层要开:
、
—— 这决定了它对哪些 MIME 类型响应启用压缩
PHP 层建议关
,避免和 Nginx 冲突;若坚持用 PHP 控制,确保 Nginx 的
或明确设置
头,否则 CDN 可能缓存错版本
特别注意
和
:如果 PHP 输出大体积 HTML,缓冲区太小会导致 Nginx 截断响应,看起来像“压缩失效”
压缩是否起效,最终取决于客户端请求头、服务端运行时模块状态、Web 服务器配置三者交集。最容易被忽略的是中间层(CDN、反向代理)悄悄修改或清除了
或
头,调试时得逐层抓包确认。
ob_gzhandlerob_gzhandlerob_start()gzipob_gzhandlerechoWarning: ob_start(): output handler 'ob_gzhandler' cannot be used after by a previous handlertext/application/jsonapplication/javascriptob_gzhandlerContent-Encoding: gzip, gzip str_repeat('x', 2048)]);
?>zlib.output_compression = Onmod_deflateVary: Accept-Encodingzlib.output_compressionob_gzhandlerzlib.output_compressionob_gzhandlerContent-Encoding: gzipcurl -H "Accept-Encoding: gzip" -I http://yoursite.com/test.phpob_gzhandlerAccept-Encoding: gzipob_start()ob_start('ob_gzhandler')ob_list_handlers()echo str_repeat(' ', 1024)gzipgzip on;gzip_types text/plain application/json application/javascript text/css;zlib.output_compressiongzip_vary offVaryfastcgi_buffer_sizefastcgi_buffersAccept-EncodingVary