企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# PHP缓冲区 >PHP中有一个"输出缓冲区"层!首先要明确"输出缓冲区"是基于PHP5.4(以及以上版本),PHP中的OB层从5.4版开始就发生了很多变化,确切说是完全重写了,有些地方可能都不兼容PHP 5.3了。 ## 什么是输出缓冲区? PHP的输出流包含很多字节,通常都是程序员要PHP输出的文本,这些文本大多是echo语句或者printf()函数输出的。首先要明确,PHP的任何输出都会用到缓冲区,但是如果是用PHP编辑扩展,用到的函数(C函数)可能会直接输出写到SAPI缓冲区,而不红过OB层。 >[danger]"输出缓冲区层"不是惟一用于缓冲区输出的层,它实际上只是很多层中的一个。并且`输出缓冲区层`与使用的(web和cli)有关。不同的SAPI可能有不同的行为。 >[info]CLI的SAPI有点特殊。CLI会将INI配置中的output_buffer选项强制设置为0,这表示禁用默认PHP输出缓冲区。所以在CLI中,默认情况下你要输出的东西会直接传递到SAPI层,除非你手动调用ob_()类函数。并且在CLI中,implicit_flush的值也会被设置为1。 ## 默认PHP输出缓冲区 如果你使用不同于CLI的SAPI,像PHP-FPM,你会用到下面三个跟缓冲区相关的INI配置选项: - output_buffering - implicit_flush - output_handler >[danger]不能在运行时使用ini_set()改这几个选项的值。这些选项的值会在PHP程序启动的时候,还没有运行任何脚本之前解析,所以也许在运行时可以使用ini_set()改变它们的值,但改变后的值并不会生效,一切都已经太迟了,因为输出缓冲区层已经启动并已激活。你只能通过编辑php.ini文件或者是在执行PHP程序的时候使用-d选项才能改变它们的值。 >[info]默认情况下,PHP发行版会在php.ini中把output_buffering设置为4096个字节。如果你不使用任何php.ini文件(或者也不会在启动PHP的时候使用-d选项),它的默认值将为0,这表示禁用输出缓冲区。如果你将它的值设置为“ON”,那么默认的输出缓冲区的大小将是16kb。你可能已经猜到了,在web应用环境中对输出的内容使用缓冲区对性能有好处。默认的4k的设置是一个合适的值,这意味着你可以先写入4096个ASCII字符,然后再跟下面的SAPI层通信。并且在web应用环境中,通过socket一个字节一个字节的传输消息的方式对性能并不好。更好的方式是把所有内容一次性传输给服务器,或者至少是一块一块地传输。层与层之间的数据交换的次数越少,性能越好。你应该总是保持输出缓冲区处于可用状态,PHP会负责在请求结束后把它们中的内容传输给终端用户,你不用做任何事情。 >[danger]implicit_flush已在前面谈论CLI的时候提到过。对于其他的SAPI,implicit_flush默认被设置为关闭(off),这是正确的设置,因为只要有新数据写入就刷新SAPI的做法很可能并非你所希望的。对于FastCGI协议,刷新操作(flushing)是每次写入后都发送一个FastCGI数组包(packet),如果发送数据包之前先把FastCGI的缓冲区写满会更好一些。如果你想手动刷新SAPI的缓冲区,使用PHP的flush()函数。如果你想写一次就刷新一次,你可以设置INI配置中的implicit_flush选项,或者调用一次ob_implicit_flush()函数。 >[success]output_handler是一个回调函数,它可以在缓冲区刷新之前修改缓冲区中的内容。PHP的扩展提供了很>[success]多回调函数(用户也可以自己编写回调函数)。 - ob_gzhandler : 使用ext/zlib压缩输出 - mb_output_handler : 使用ext/mbstring转换字符编码 - ob_iconv_handler : 使用ext/iconv转换字符编码 - ob_tidyhandler : 使用ext/tidy整理输出的HTML文本 - ob_[inflate/deflate]_handler : 使用ext/http压缩输出 - ob_etaghandler : 使用ext/http自动生成HTTP的Etag >[success]缓冲区中的内容会传递给你选择的回调函数(只能用一个)来执行内容转换的工作,所以如果你想获取PHP传输给web服务器以及用户的内容,你可以使用输出缓冲区回调。当前有一点也需要提一下,这里说的“输出”指的是消息头(headers)和消息体(body)。HTTP的消息头也是OB层的一部分。