php缓存,开启output_buffering的情况下,如何分段输出?
发布于 作者:苏南大叔 来源:程序如此灵动~本文还是接着讨论php
内容分段分步输出的问题,前提依然是仅使用php
开启服务,不掺合nginx
什么事情。当关闭output_buffering
的情况下,无论是否加flush()
函数调用,最终效果都是符合需求的。那么,开启output_buffering
的情况下,又如何实现分步输出的需求呢?
苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验总结。本文测试环境:win10
,php-cgi@8.2.11nts
,chrome@120.0.6099.201
。
前文回顾
在下面这篇文章里面,提出了分段输出的需求:
然后又提出了一个可能的解决方案,关于flush()
函数的调用问题:
然后就提出了本文的主要内容,在开启output_buffering
的情况下,如何依然实现分步输出及时显示的需求。不明白本文需求的,可以查看前两篇文章。
一语天机
实际上php.ini
的output_buffering
选项,就相当于php
代码里面的ob_start()
。那么,开启output_buffering
的话,就相当于代码里面,自动执行了ob_start()
,只是代码里面不能设置这个缓存的大小而已。
那么,无论是否开启缓存,做到分段及时输出的重要前提就是:破坏这个缓存机制。那么,方法就很多了。设置output_buffering
为off
,就是最简单的方案。
那么,在开启output_buffering
为1024
字节的情况下,依然是可以实现分步输出的需求的。(虽然上一篇文章里面的代码,没能实现)。
output_buffering = 1024
方案一,ob_end_clean()
开启了output_buffering
,意味着代码里面有个隐藏的ob_start()
。那么,输出的内容,就必然会被缓存掉。所以,在代码的顶部,加个ob_end_clean()
,就相当于把缓存效果给关闭了。客观上也就相当于关闭了output_buffering
。所以,后面的输出内容,直接echo
即可,无需flush()
之类的函数。
ob_end_clean();
echo "output_buffering:",ini_get("output_buffering"), "<br/>";
sleep(3);
echo date("i:s",time()), PHP_EOL;
sleep(3);
方案二,ob_flush()
还记得上一篇文章里面写到,开启output_buffering
,然后使用flush()
函数的情况下,刷新的时候,会出现白屏的情况。那么,如果在flush()
之前,加上一个ob_flush()
的话,就可以避免空白的情况。这是因为:
ob_flush()
负责把内容从系统缓存里面输出。flush()
负责把内容再输出到浏览器端。
echo "output_buffering:",ini_get("output_buffering"), "<br/>";
ob_flush();
flush();
sleep(3);
echo date("i:s",time()), PHP_EOL;
ob_flush();
flush();
sleep(3);
ob_end_flush()
也有类似的效果,但是这里有个end
的效果在里面。所以,并不是可以重复的行为。所以,可以根据情况使用了。
方案三,ob_implicit_flush()
ob_implicit_flush()
,这个函数翻译一下,就是“含蓄的flush”。但是,苏南大叔的理解下,和官方或者网路上的各种教程是不同的。其它地方说的是在echo
后会含蓄的flush()
,但是,苏南大叔测试的结果是:是在ob_flush()
后才会含蓄的flush()
。
ob_implicit_flush()
,就相当于ob_implicit_flush(true)
。但是,苏南大叔目前也想不到ob_implicit_flush(false)
的使用场景。
ob_implicit_flush();
echo "output_buffering:",ini_get("output_buffering"), "<br/>";
ob_flush();
sleep(3);
echo date("i:s",time()), PHP_EOL;
ob_flush();
sleep(3);
特别说明
本文的这几个代码,针对的是开启output_buffering
的情况下,都是能满足分段及时输出的需求的。那么,在关闭output_buffering
的情况下,这些代码会有一些warning
信息输出。但是,依然满足需求。
所以,大家可以根据情况编写更兼容的代码。这个不难,大家自己研究。
思考题目
下面的代码里面,看看到底能不能分段输出呢?
ob_implicit_flush();
echo "output_buffering:",ini_get("output_buffering"), "<br/>";
sleep(1);
echo "关闭buffer的话,前后有停顿,否则没有。<br/>";
sleep(1);
for ($i = 0; $i < 3; $i++) {
echo "$i\n";
@ob_flush();
sleep(1);
}
效果是非常好的,前两个echo()
是直接输出的,虽然有sleep(1)
。但是后面输出里面,因为ob_flush()
以及隐藏的flush()
效果,是分段及时输出的。这个例子可以很好的解释最近的几篇文章。
结语
再次说明,本文的代码是基于纯php
的前提下,没有设置nginx
设置。因为nginx
里面也有缓存,会破坏所有已有的效果。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。