之前转了一篇关于php输出缓冲控制的文章:http://blog.csdn.net/adslcom/article/details/8282342 用来方便之后查看的。对于内容的例子代码也没有一一测试,今天调试了一下,发现自己对php输出缓冲的理解还是不够,导致在调试过程中发现很多不解的情况。经过一番google和测试,总算明白了一些。这里记录一下,也方便大家看看我的理解是否有误。
针对上篇文章的例子3和4:
<?php
/*例3*/
echo str_pad('', 1024);//使浏览器缓冲区溢出
ob_start();//打开缓冲区
echo 'oschina.net';
ob_flush();//送出当前缓冲内容,不会输出
flush();//输出送出的缓冲内容
sleep(1);
echo '红薯';
ob_flush();//送出当前缓冲内容,不会输出
flush();//输出送出的缓冲内容
sleep(1);
echo '虫虫';
ob_end_flush();//输出并关闭缓冲
?>
例子4:
<?php
/*例4*/
echo str_pad('', 1024);//使浏览器缓冲区溢出
echo 'oschina.net';
flush();//输出送出的缓冲内容
sleep(1);
echo '红薯';
flush();//输出送出的缓冲内容
sleep(1);
echo '虫虫';
?>
要达到实时显示,每隔1秒显示一个。前提是php.ini的output_buffering是关闭的,即output_buffering=Off(为了灵活调用flush(),implicit_flush = Off一直是关闭的)。
好的,现在来说说为什么?
先说说php输出顺序吧。如图:
php输出缓冲是支持嵌套的,可堆叠的。如果output_buffering=On,默认就开启了一个buffer。这个buffer肯定是最外层的。调用ob_start()就是手动开启一个buffer。
例子3,如果output_buffering=On,那就默认开启了一个buffer,先命名为buffer1,然后程序调用ob_start(),手动开启另一个buffer,命名为buffer2。调用ob_flush把buffer2的内容输出到上一层buffer1去,然后调用flush,flush是针对
server buffering的,刷新server buffering的缓冲,输出到浏览器去显示。现在的问题是数据还在buffer1即php output_buffering这个阶段,而server buffering还没有数据。所以数据没有实时显示出来。
例子4,正是output_buffer=Off,所以echo的内容直接到server buffering去了,然后调用flush,flush就会把server buffering的数据输出到浏览器去。如果output_buffering开启了,那数据就到php的output_buffering那,flush就没有效果了。
那如果output_buffering=On,上面的代码怎么修改了?
最简单是先关闭默认开启的buffer就可以了:
<?php
/*修改的例3*/
echo ob_get_level();// 1,默认开启了一个buffer
ob_end_clean();//清空,删除默认开启的buffer
echo ob_get_level();// 0,删除了
echo str_pad('', 1024);//使浏览器缓冲区溢出
ob_start();//打开缓冲区
echo 'oschina.net';
ob_flush();//送出当前缓冲内容,不会输出
flush();//输出送出的缓冲内容
sleep(1);
echo '红薯';
ob_flush();//送出当前缓冲内容,不会输出
flush();//输出送出的缓冲内容
sleep(1);
echo '虫虫';
ob_end_flush();//输出并关闭缓冲
?>
复杂的点:
<?php
/*修改的例3*/
echo str_pad('', 1024);//使浏览器缓冲区溢出
ob_start();//打开缓冲区buffer2
echo 'oschina.net';
ob_end_flush();//把buffer2的内容输出到buffer1,关掉buffer2
ob_flush();//把buffer1的内容输出到server buffer
flush();//输出送出的缓冲内容
sleep(1);
ob_start();//buffer2
echo '红薯';
ob_end_flush;//同上
ob_flush();//同上
flush();//输出送出的缓冲内容
sleep(1);
ob_start();//buffer2
echo '虫虫';
ob_end_flush();//同上
ob_flush();//同上
flush();
?>
分析得出:
ob_end_flush、ob_flush针对的是php buffering,flush针对的是server buffering。只有php buffering到了最外层,再调用ob_flush or ob_end_flush才是把数据从php buffering出到server buffering。如果不是最外层,那只是送出到外层的
php buffering去而已。然后还有一个问题就是浏览器缓冲,在执行之前,都会先输出1024个字节数,就是为了浏览器的缓冲溢出。问题是为什么这个输出不会给php buffering起来,可以直接输出?还是说哪块理解错误了?大家知道的就麻烦告诉小弟啦,上面的分析有错的也请指出来,谢谢啦!