本篇文章给大家带来的内容是关于php输出缓冲区的详细介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
PHP输出缓冲区:
缓冲区:实际上是一个内存地址空间。它用来存储速度不同步的设备或者优先级不同的设备之间传输数据的区域。通过缓冲可以使进程之间的交互时间等待变小,从而使从速度慢的设备读取数据时,速度快的设备的操作进程不发生间断
PHP的输出流包含很多内容,通常都是开发者要PHP输出的文本,这些文本大多是用echo或printf()函数来输出的
1>任何输出内容的函数都会用到输出缓冲区
这是指正常的PHP脚本,如果开发的是PHP扩展,使用的函数(C函数)可能会直接输出写到SAPI缓冲区层,不需要经过输出缓冲层(我们可以在PHP源文件 main/php_output.h了解这些C函数的API文档)
2>输出缓冲区不是唯一用于缓冲输出的层,它实际上只是很多层中的一个,输出缓冲层的行为与使用的SAPI(Web或CLI)有关,不同的SAPI可能有不同的行为
![63127257a167ee6e5186cf6d76b6c106.png](https://i-blog.csdnimg.cn/blog_migrate/083289273a9a6fb95bf8ff43b4bc83c9.jpeg)
缓冲逻辑关系图
最上端的两次就是我们通常所认识的‘输出缓冲区’
3>SAPI中的输出缓冲区,这些都是PHP中的层,当输出的字节离开PHP进入计算机体系结构中的更底层时,缓冲区又会不断出现(终端缓冲区(terminal buffer)、fast-cgi缓冲区、Web服务器缓冲区、操作系统缓冲区、TCP/IP栈缓冲区等)。
PHP CLI的SAPI有点特殊,CLI也称命令行界面,它会将php.ini配置中output_buffer选项强制设置为0,这表示禁用默认PHP输出缓冲区,所以在CLI中,默认情况下你要输出的内容会直接传递到SAPI层,除非你手动调用ob_()类函数,并且在CLI中,implicit_flush的值也会被设置为1,
注:我们经常混淆implicit_flush的作用,php的源代码已说明一切:当implicit_flush被设置为打开(值为1)时,一旦有任何输出写到SAPI缓冲区,它都会立刻刷新(flush,意思把这些数据写到更底层,并且缓冲区会被清空)
也就是说任何数据到CLI SAPI中时,CLI SAPI都会立即将这些数据仍到它的下一层去,一般会是标准输出管到,write()和fflush()这两个函数就是负责做这件事情的
默认PHP输出缓冲区:如果使用不同于CLI的SAPI,比如PHP-FPM,会用到下面3个与缓冲区相关的php.ini配置选项
output_buffering
implicit_flush
output_handler
首先不能再运行时使用ini_set()函数修改这几个选项的值,因为这些值会在PHP程序启动的时候,还没有运行任何脚本之前解析,所以在运行时可以使用ini_set()改变值,但是并不会生效。我们只能通过编辑php.ini文件或者是在执行PHP程序的时候使用-d选项才能改变它们的值
默认情况下,PHP发行版会在php.ini中会把output_buffering设置为4096个字节,如果将它的值设置为ON,那么默认的输出缓冲区的大小为16KB
在Web应用环境中对输出的内容使用缓冲区对性能有好处:
默认的4K的设置是一个合适的值,意味着你可以先写入4096个ASCLL字符,然后在与下面的SAPI层通信,并且在Web应用环境中,通过Socket一个字节一个字节地传输消息的方式对性能并不好,更好的方式是把所有内容一次性传输给服务器,或者至少是一块一块地传输,层与层之间的数据交换次数越少,性能越好,应该总是保持输出缓冲区处于可用状态,PHP会负责在请求结束后把它们中的内容传输给终端用户,开发者不用做任何事
implicit_flush默认是设置为关闭,这样的话新数据写入就不会刷新SAPI,对于FastCGI协议,刷新操作是每次写入后都发送一个FastCGI数组包,如果发送数据包之前先把FastCGI的缓冲器写满会更好。如果需要手动刷新SAPI的缓冲区,使用flush()函数,如果想写一个就刷新一次可以设置implicit_flush或者调用一次ob_implicit_flush()函数
推荐使用配置:
output_buffering=4096
implicit_flush = Off/no
要修改输出缓冲区的大小,硬确保使用的值是4/8的倍数,它们分别是32/64位操作系统
output_handler是一个回调函数,它可以在缓冲区刷新之前修改缓冲区中的内容
缓冲区中的内容会传递给你选择的回调函数(只能用一个)来执行内容转换的工作,所以说如果想获取PHP给Web服务器以及用户的内容,可以使用输出缓冲区回调,输出是指:消息头、消息头。HTTP的消息头也是输出缓冲区层的一部分
消息头和消息体:
实际上,任何与消息头的输出有关的PHP函数(header()、setcookie()、session_start())都使用内部的sapi_header_op函数,这个函数只会把内容写入消息头缓冲区中。 当我们如使用printf()函数的时候,内容会先被写入到输出缓冲区(可能是多个),当这个输出环城区的内容需要被发送的时候,PHP会先发送消息头,然后发送消息体。PHP为了搞定了所有的事情,如果想自己动手,那就只能禁掉输出缓冲区
用户输出缓冲区:
如果想使用默认PHP输出缓冲区层,就不能使用CLI,因为它已经禁用了这个层
/*launched via php -d output_buffering=32 -d implicit_flush=1 * */echo str_repeat('a',31);sleep(3);echo 'b';sleep(3);echo 'c';?>
默认输出缓冲区的大小设置32字节,程序运行会先写入31字节,然后休眠,然后在写入1一个字节,这个字节填满缓冲区,它会立即刷新自身,把里面的数据传递给SAPI层的缓冲区,因为把implicit_flush设置为1,所以SAPI层的缓冲区也会立即刷新到下一层,所以输出aa...b,然后休眠,然后在输出一个字节,此时缓冲区有31空字节,但是脚本执行完毕,所以包含这个字节的缓冲区也会立即刷新,从而会在屏幕输出c
用户输出缓冲区:通过ob_start()创建,我们可以创建多个这种缓冲区(直到内存耗尽为止),这些缓冲区组成一个堆栈结构,每个新建缓冲区都会堆叠到之前的缓冲区上,每次当它被填满或者溢出,都会执行刷新操作,然后把其中的数据传递给下一个缓冲区
function callback($buffer){ // replace all the apples with oranges return ucfirst($buffer);} function callback1($buffer){ // replace all the apples with oranges static $a=0; return $a++.'-'.$buffer."";}ob_start('callback1',10);ob_start("callback