【无标题】

‌**ob_get_level函数用于获取当前输出缓冲区的嵌套级别**‌。如果输出缓冲区未启用,则返回0;如果启用了输出缓冲区,则返回当前的嵌套级别‌12。

输出缓冲区的嵌套级别

输出缓冲区处理函数的作用类似于堆栈,用于临时存储输出内容,处理后再输出。每次调用ob_start()都会开启一个新的缓存区,相当于增加一层嵌套。例如:

  • ob_start(); 开启第一个缓存区,嵌套级别为1。
  • ob_start(); 开启第二个缓存区,嵌套级别为2。
  • ob_start(); 开启第三个缓存区,嵌套级别为3。

通过调用ob_get_level()可以获取当前的嵌套级别。例如:

  • 在第一个ob_start()后调用ob_get_level()会返回1。
  • 在第二个ob_start()后调用ob_get_level()会返回2。
  • 在第三个ob_start()后调用ob_get_level()会返回3‌12。

输出缓冲区的配置和使用场景

php.ini配置文件中,可以通过设置output_buffering来启用或禁用输出缓冲区。默认值为4096字节。当输出缓冲区启用时,输出的顺序为:PHP输出缓冲 -> 服务器缓冲 -> 浏览器缓冲 -> 浏览器显示。如果未启用输出缓冲区,输出的顺序则为:服务器缓冲 -> 浏览器缓冲 -> 浏览器显示‌12。

通过使用输出缓冲控制函数,如ob_start(), ob_get_contents(), ob_end_clean(), 和 ob_end_flush(),可以实现对输出的灵活控制。

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刷出,都是由位于队尾缓冲区块向上一级缓冲区块刷出,且区块里的内容不是替换,而是叠加。
相关推荐
哲科软件3 小时前
跨平台开发的抉择:Flutter vs 原生安卓(Kotlin)的优劣对比与选型建议
android·flutter·kotlin
浪裡遊4 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
jyan_敬言10 小时前
【C++】string类(二)相关接口介绍及其使用
android·开发语言·c++·青少年编程·visual studio
程序员老刘10 小时前
Android 16开发者全解读
android·flutter·客户端
ejinxian11 小时前
PHP 超文本预处理器 发布 8.5 版本
开发语言·php
福柯柯11 小时前
Android ContentProvider的使用
android·contenprovider
不想迷路的小男孩11 小时前
Android Studio 中Palette跟Component Tree面板消失怎么恢复正常
android·ide·android studio
餐桌上的王子11 小时前
Android 构建可管理生命周期的应用(一)
android
菠萝加点糖11 小时前
Android Camera2 + OpenGL离屏渲染示例
android·opengl·camera
用户20187928316711 小时前
🌟 童话:四大Context徽章诞生记
android