ob_get_level(void):int
- 返回嵌套的输出缓冲处理程序的级别;或者是,如果输出缓冲区不起作用,返回零。
php.ini中配置缓冲
在php的配置文件php.ini中有以下这项配置 output_buffering
,php.ini默认设置了output_buffering = 4096,php已经设置了一个缓冲区。
如果php.ini 中打开了此项: echo,print 后的输出顺序就是-> php output_buffring -> server buffering -> browser buffering -> browser display;
如果未打开php输出缓存: echo,print 后的输出顺序就是-> server buffering -> browser buffering -> browser display.
如果 php.ini 开启了缓存,则 ob_get_level() 得到的值会是1,相当于都执行了一次ob_start(),配置output_buffering = 0,嵌套级别的值会为0。
如果总是希望在脚本的开头有一个输出缓冲区,则可以使用
if (!ob_get_level()) ob_start();
在脚本的开头这样写,相当于可以关闭 php.ini 中设置的缓存区
缓存嵌套级别的理解
输出缓冲区处理函数的作用有点类似堆栈,临时放入一个存储空间中,对内容进行处理。类似队列一样,但是不是先进先出,而是先开后关,缓存区关闭的顺序是从下到上。
ob_start() 每执行一次,就会开启一个新的缓存区。
先看个例子:
// php.ini中开启了缓存区,相当于都已执行一次 ob_start() (理解名为 buffer_A 区块)
echo '(buffer_A)'; //缓存 buffer_A 区 保存了下面的所有输出
echo ob_get_level(); #输出1
ob_start(); #开启一个缓存区(理解名为 buffer_B 区块)
echo '(buffer_B)'; //缓存 buffer_B 区 保存了下面的所有输出(不包括A区的内容)
echo ob_get_level(); #输出2
ob_start(); #开启一个缓存区(理解名为 buffer_C 区块)
echo '(buffer_C)'; //缓存 buffer_C 区 保存了下面的所有输出(不包括 A&B 区的内容)
echo ob_get_level(); #输出3
echo "<br>---------------------<br>";
//第1次获取输出缓存区的内容是最后一个缓冲区的内容:输出 buffer_C 区范围下的内容
//echo ob_get_contents(); # 输出 3(buffer_C)
//第1次关闭的缓冲区是最后一个缓存区:buffer_C
ob_end_flush(); #关闭缓存区(buffer_C )
//关闭1个缓存区后,第二次获取缓存区的内容:输出的是 buffer_B 区 范围下的内容,
//echo ob_get_contents(); # 输出 2(buffer_B)3(buffer_C)
//第2次关闭的缓冲区:buffer_B
ob_end_flush();
//关闭2个缓存区后,第三次获取缓存区的内容:输出的是 buffer_A 区 范围下的内容,
//echo ob_get_contents(); # 输出 (buffer_A)1(buffer_B)2(buffer_C)3
//第3次关闭的缓冲区:buffer_A,此时所有的缓冲区都被清了
ob_end_flush();
echo ob_get_contents(); # 没有内容输出
通过 ob_get_contents()
每次获取到的缓存区的内容可得到,每个缓冲区保存的内容都是在他下面范围的内容。
这个“下面”怎么理解,如例中:buffer_A
区保存A,B,C 这3区的内容,buffer_B
区保存的是B,C 这2区的内容,buffer_C
区保存的是 C 这1区的内容。
而 ob_end_flush()
每次关闭都是后面的缓冲区,关闭的顺序是从下到上的关闭,也是先开后关,后开先关
,就如排队一样,start 开启时是按照顺序开启,关闭时是从队伍后面开始关闭。
如例子,最先关闭的是 C区,然后 B 区,最后 A 区 。(start开启缓冲区是进队:A,B,C ,end关闭缓存区是出队: C,B,A)
理解好每个缓存区保存的是“所属下面的内容”,第一次开启的缓存区是最顶级的,下面所有子级的内容都在上游的缓存区中。
理解要点
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刷出,都是由位于队尾缓冲区块向上一级缓冲区块刷出,且区块里的内容不是替换,而是叠加。