首先,我们需要明确PHP的输出顺序。当打开了PHP输出缓存时,输出顺序为:echo、print -> php output buffering -> server buffering -> browser buffering -> browser display。而当未打开PHP输出缓存时,输出顺序为:echo、print -> server buffering -> browser buffering -> browser display。
接下来,我们需要了解浏览器的输出缓存。IE的输出缓存大小为256Bytes,Chrome和Firefox的输出缓存大小为1000Bytes。只有当输出数据达到这个长度或者脚本结束时,浏览器才会将数据输出在页面上。
现在我们来看一下用到的几个PHP设置和API:
1. php.ini中的output_buffering配置:
- Off:表示关闭PHP输出缓存
- On:打开无限大的输出缓存
- 4096:打开大小为4096Byte的输出缓存
2. php.ini中的implicit_flush配置:
- On:表示每次输出(如echo,print)后自动调用flush()函数后,直接输出
- Off:与On相反,每次输出后不会调用flush(),需要等到server buffering满了才会输出,但是我们可以用flush()函数代替它,不开启也没关系,反而更加灵活
3. ob_flush()函数:取出PHP buffering中的数据,放入server buffering
4. flush()函数:取出Server buffering的数据,放入browser buffering
5. ob_start()函数:对于这个函数我现在了解的不是很清楚,因为开启后输出就会不受ob_flush()控制,即使使用ob_flush()和flush(),数据也不能立即输出在浏览器上。现在知道的是,如果output_buffering=Off,即使使用了ob_start(),也是无法将输出数据缓存的,而如果output_buffering=On的话,即使不用ob_start(),输出数据也可以被PHP缓存,所以觉得ob_start比较废,暂时不管他。
最后,我们来看一下代码(设置output_buffering=4096,implicit_flush=Off):
```php
// 设置output_buffering为4096,implicit_flush为Off
?>
```
// ob_start(); //这玩意开了就会不正常,输出不受ob_flush()控制,不知道到底干嘛用
// echo str_repeat(' ' ,1000); //IE缓存256Bytes
echo str_repeat(' ' ,1000); //Chrome和FF缓存1000Bytes,这里用来先将浏览器缓存用掉,但是很疑惑这一行输出为什么没有被output_buffering存起来,而是直接输出了
for($i=0;$i<5;$i++) {
echo $i.'<br />';
ob_flush();
flush();
sleep(1);
}
?>
这里的代码输出结果是一行一行输出的,具体原理大家参考一下ob_flush()和flush()函数的功效。这两个函数缺了任何一个在我这种设置下都是要等到 0, 1, 2, 3, 4都缓存起来后最后一起输出。最后引用一段Laruence的一段blog,希望对大家的理解有帮助:ob_flush/flush在手册中的描述,都是刷新输出缓冲区,并且还需要配套使用,所以会导致很多人迷惑...其实,他们俩的操作对象不同,有些情况下,flush根本不做什么事情..ob_*系列函数,是操作PHP本身的输出缓冲区。所以,ob_flush是刷新PHP自身的缓冲区。而flush,严格来讲,这个只有在PHP做为apache的Module(handler或者filter)安装的时候,才有实际作用。它是刷新WebServer(可以认为特指apache)的缓冲区。在apache module的sapi下,flush会通过调用sapi_module的flush成员函数指针,间接地调用apache的api:ap_rflush刷新apache的输出缓冲区。当然手册中也说了,有一些apache的其他模块,可能会改变这个动作的结果。1.有些Apache的模块,比如mod_gzip,可能自己进行输出缓存。2.这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。3.
.甚至在浏览器显示之前,它也会缓存接收到的内容。例如,Netscape浏览器会在接受到换行或HTML标记的开头之前缓存内容,并且在接收到标记之前,不会显示出整个表格。
5.这种现象可能会导致网页的显示不完整或者出现错误。为了解决这个问题,我们需要了解一些与浏览器缓存相关的知识。
6.有些版本的Microsoft Internet Explorer只有在接收到256个字节以后才开始显示该页面,所以在这种情况下,我们必须发送一些额外的空格来确保这些浏览器能够正确显示页面内容。
7.因此,在使用这些浏览器时,我们需要正确地使用ob_flush和flush这两个函数的顺序。首先调用ob_flush,然后调用flush。当然,在其他sapi环境下,不调用flush也是可以的,但为了保证代码的可移植性,建议配套使用这两个函数。
8.总之,浏览器缓存是一个需要我们关注的问题。通过了解浏览器缓存的行为和如何正确使用ob_flush和flush这两个函数,我们可以确保网页在各种浏览器中的显示效果更加完美。
您可能感兴趣的文章:为什么需要了解浏览器缓存以及如何正确使用ob_flush和flush函数?