基于PHP输出缓存(output_buffering)的深入理解


Posted in PHP onJune 13, 2013

首先明确一下PHP的输出顺序
1.打开了php输出缓存: echo,print -> php output_buffring -> server buffering -> browser buffering -> browser display
2.未打开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)

<html>
     <body>
         <?php
             // 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);
             }
         ?>
     </body>
 </html>

这里代码输出结果是一行一行输出的,具体原理大家参考一下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.
4.甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape
5.浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在
6.接受到 </table> 标记之前,不会显示出整个表格。
7.
8.一些版本的 Microsoft Internet Explorer 只有当接受到的256个
9.字节以后才开始显示该页面,所以必须发送一些额外的空格来让这
10.些浏览器显示页面内容。
所以, 正确使用俩者的顺序是. 先ob_flush, 然后flush,
当然, 在其他sapi下, 不调用flush也可以, 只不过为了保证你代码的可移植性, 建议配套使用.

PHP 相关文章推荐
使用数据库保存session的方法
Oct 09 PHP
php学习笔记(三)操作符与控制结构
Aug 06 PHP
php中将数组存到文件里的实现代码
Jan 19 PHP
基于PHP5魔术常量与魔术方法的详解
Jun 13 PHP
解决file_get_contents无法请求https连接的方法
Dec 17 PHP
php中simplexml_load_string使用实例分享
Feb 13 PHP
php实现的一个简单json rpc框架实例
Mar 30 PHP
php socket通信(tcp/udp)实例分析
Feb 14 PHP
微信公众平台DEMO(PHP)
May 04 PHP
对比PHP对MySQL的缓冲查询和无缓冲查询
Jul 01 PHP
php+redis消息队列实现抢购功能
Feb 08 PHP
PHP实现微信提现功能
Sep 30 PHP
php缓冲 output_buffering的使用详解
Jun 13 #PHP
如何在PHP中使用正则表达式进行查找替换
Jun 13 #PHP
php启用zlib压缩文件的配置方法
Jun 12 #PHP
Window下PHP三种运行方式图文详解
Jun 11 #PHP
控制PHP的输出:缓存并压缩动态页面
Jun 11 #PHP
基于PHP导出Excel的小经验 完美解决乱码问题
Jun 10 #PHP
win7+apache+php+mysql环境配置操作详解
Jun 10 #PHP
You might like
Php+SqlServer实现分页显示
2006/10/09 PHP
PHP中使用匿名函数操作数据库的例子
2014/11/17 PHP
支付宝支付开发――当面付条码支付和扫码支付实例
2016/11/04 PHP
PHP魔术方法之__call与__callStatic使用方法
2017/07/23 PHP
php字符串函数 str类常见用法示例
2020/05/15 PHP
javascript String 对象
2008/04/25 Javascript
jquery 简短右键菜单 多浏览器兼容
2010/01/01 Javascript
Javascript实现的鼠标经过时播放声音
2010/05/18 Javascript
js对文章内容进行分页示例代码
2014/03/05 Javascript
javascript中call和apply的用法示例分析
2015/04/02 Javascript
jQuery实现分章节锚点“回到顶部”动画特效代码
2015/10/23 Javascript
Bootstrap 3.x打印预览背景色与文字显示异常的解决
2016/11/06 Javascript
JS Testing Properties 判断属性是否在对象里的方法
2017/10/01 Javascript
vue实现可视化可拖放的自定义表单的示例代码
2019/03/20 Javascript
Python二分法搜索算法实例分析
2015/05/11 Python
新手如何快速入门Python(菜鸟必看篇)
2017/06/10 Python
Python获取本机所有网卡ip,掩码和广播地址实例代码
2018/01/22 Python
python 实现selenium断言和验证的方法
2019/02/13 Python
django-rest-swagger的优化使用方法
2019/08/29 Python
Django 自定义分页器的实现代码
2019/11/24 Python
Python scrapy爬取小说代码案例详解
2020/07/09 Python
python中的列表和元组区别分析
2020/12/30 Python
浅析HTML5的WebSocket与服务器推送事件
2016/02/19 HTML / CSS
为智能设备设计个性化保护套网站:caseable
2017/01/05 全球购物
手机配件第一品牌:ZAGG
2017/05/28 全球购物
惊艳的手工时装首饰:Migonne Gavigan
2018/02/23 全球购物
中学生自我评价范文
2014/02/08 职场文书
学生评语大全
2014/04/18 职场文书
小学优秀班主任事迹材料
2014/05/17 职场文书
亮剑精神演讲稿
2014/05/23 职场文书
2015年幼儿园元旦亲子活动方案
2014/12/09 职场文书
市场总监岗位职责
2015/02/11 职场文书
详解如何在Canvas中添加事件的方法
2021/04/17 Javascript
RestTemplate如何通过HTTP Basic Auth认证示例说明
2022/03/17 Java/Android
GTX1650super好不好 gtx1650super显卡属于什么级别
2022/04/08 数码科技
微信小程序 根据不同用户切换不同TabBar
2022/04/21 Javascript