我理解的要点:
1、所有缓冲区控制是在一个php执行进程中发生的。如:你打开n个demo.php,他们之间开启和关闭缓冲是互不影响的。
2、output_buffering在程序中用ini_set是不能生效的。
3、所有缓冲区数据,如果没有手工flush刷出,则在程序结束会被解释器刷出。
4、关于嵌套级别:当顺序开启多个ob_start()时,会相应开启多个缓冲区。可以理解成队列,队伍成员是ob_start()开启的缓冲区块,而ob_get_level()可理解成当前队伍最末尾的缓冲块的序列号。
5、每次echo,print输出的内容都是针对队尾的缓冲区块进行的。
6、每次ob[end][flush|clean]函数也都是针对队尾缓冲区块进行的。
7、每次执行flush刷出,都是由位于队尾缓冲区块向上一级缓冲区块刷出,且区块里的内容不是替换,而是叠加。
看例子
echo ob_get_level(),一般情况下输出:
1
因为php.ini默认设置了output_buffering = 4096,这代表着不管程序里面怎么写,php已经设置了一个缓冲区。
该缓冲区可以手工关闭:
ob_end_clean();
echo ob_get_level();
这时程序输出:
0
如果再加一条ob_end_clean()就会看到提示:
Notice: ob_end_clean(): failed to delete buffer. No buffer to delete
更改php.ini,修改配置output_buffering = 0,再看echo ob_get_level(),输出:
0
将配置修改成output_buffering = 4096,恢复初始状态。
进入例子:
<?php
echo ob_get_level(),‘<br/> ‘;
ob_start();
echo ob_get_level(),‘<br/> ‘;
ob_start();
echo ob_get_level(),‘<br/> ‘;
?>
输出:
1
2
3
因为output_buffering = 4096,默认存在一个缓冲区(理解名为”buffer_A”区块),所以第一次echo ob_get_level()结果为1;
ob_start()开启了一个缓冲区(理解名为”buffer_B”区块),这时echo ob_get_level()结果为2.
level有点类似数组元素的下标+1
当ob_start()再开启一个缓冲区(理解名为”buffer_C”区块),这时echo ob_get_level()结果为3.
再看例子:
<?php
echo ob_get_level(),‘<br/> ‘;
ob_start();
echo ob_get_level(),‘<br/> ‘;
ob_start();
echo ob_get_level(),‘<br/> ‘;
ob_end_clean();
echo ob_get_level(),‘<br/> ‘;
?>
结果是
1
2
2
因为output_buffering = 4096,默认存在一个缓冲区(理解名为”buffer_A”区块),所以第一次echo ob_get_level()结果为1,且该结果是保存在”buffer_A”区块中;
第一次ob_start()开启了一个缓冲区(理解名为”buffer_B”区块),这时echo ob_get_level()结果为2,且该结果是保存在”buffer_B”区块中。
第二次ob_start()再开启一个缓冲区(理解名为”buffer_C”区块),这时echo ob_get_level()结果为3,且该结果是保存在”buffer_C”区块中
到此为止,所有输出并没有直接发送到web服务器。
这时调用ob_end_clean(),将会把”buffer_C”区块给删除掉,所以结果3就不存在了
再次echo ob_get_level()时,因为没有”buffer_C”区块,所以当前应该是2,且结果保存在”buffer_B”中。
如果把ob_end_clean()改成ob_end_flush()
结果是
1
2
3
2
原理和上面一样,只是ob_end_flush()并没有直接把”buffer_C”区块中的内容直接清除,而是先把区块中的内容flush到他的上一级缓冲区块”buffer_B”中了。这时”buffer_B”区块中的内容变成了"2<br>"."3<br>"
。然后再删除缓冲区块”buffer_C”