我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

本文还是接着讨论php内容分段分步输出的问题,前提依然是仅使用php开启服务,不掺合nginx什么事情。当关闭output_buffering的情况下,无论是否加flush()函数调用,最终效果都是符合需求的。那么,开启output_buffering的情况下,又如何实现分步输出的需求呢?

苏南大叔:php缓存,开启output_buffering的情况下,如何分段输出? - output_buffering开启后,如何分段及时输出
php缓存,开启output_buffering的情况下,如何分段输出?(图3-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验总结。本文测试环境:win10php-cgi@8.2.11ntschrome@120.0.6099.201

前文回顾

在下面这篇文章里面,提出了分段输出的需求:

然后又提出了一个可能的解决方案,关于flush()函数的调用问题:

然后就提出了本文的主要内容,在开启output_buffering的情况下,如何依然实现分步输出及时显示的需求。不明白本文需求的,可以查看前两篇文章。

一语天机

实际上php.inioutput_buffering选项,就相当于php代码里面的ob_start()。那么,开启output_buffering的话,就相当于代码里面,自动执行了ob_start(),只是代码里面不能设置这个缓存的大小而已。

那么,无论是否开启缓存,做到分段及时输出的重要前提就是:破坏这个缓存机制。那么,方法就很多了。设置output_bufferingoff,就是最简单的方案。

那么,在开启output_buffering1024字节的情况下,依然是可以实现分步输出的需求的。(虽然上一篇文章里面的代码,没能实现)。

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信息输出。但是,依然满足需求。

苏南大叔:php缓存,开启output_buffering的情况下,如何分段输出? - ob_flush输出warning
php缓存,开启output_buffering的情况下,如何分段输出?(图3-2)

所以,大家可以根据情况编写更兼容的代码。这个不难,大家自己研究。

思考题目

下面的代码里面,看看到底能不能分段输出呢?

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缓存,开启output_buffering的情况下,如何分段输出? - 思考题目输出
php缓存,开启output_buffering的情况下,如何分段输出?(图3-3)

结语

再次说明,本文的代码是基于纯php的前提下,没有设置nginx设置。因为nginx里面也有缓存,会破坏所有已有的效果。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php