浅谈PHP中output_buffering


Posted in PHP onJuly 13, 2015

一、我们要说一下php中的缓存大概有哪些!

在PHP中,我们可以粗略的将缓存分为客户端缓存(Browser缓存),服务器端缓存(Server缓存)。由于PHP是基于B/S架构的,所以,我们可以理解为浏览器端的缓存,服务器端缓存。
在服务器端PHP自带的缓存中,主要可以分为两大类缓存!程序缓存和OB缓存!这也是我们学习服务器端缓存的主要内容!

在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,只有输出数据达到了这个长度或者脚本结束浏览器才会将数据输出在页面上。

二、服务器端的响应流程

A、客户端向服务器端发送请求响应!
B、Apache服务器加载了PHP模块,开启相应的进程(或线程)运行相应的PHP脚本页面!
C、在没有开启OB缓存的情况下,运行的结果全部都会被放到程序缓存中,然后打包发送给浏览器!浏览器对页面进行渲染,生成我们最后看到的WEB页面!
D、在开启了OB缓存的情况下,运行的结果会被分别放入到OB缓存和程序缓存中,当程序运行到最后一行的时候,就会将OB缓存中的数据刷回到程序缓存中,然后打包返回给浏览器!浏览器对页面进行渲染,生成我们看到的WEB页面!

三、OB缓存的常见用法!

a、output_buffering=4096,输出较少的数据(少于一个buffer)

for($i=0; $i<5; $i++){ 
 
echo $i.'<br>'; 
 
sleep(1); 
 
}

运行结果:等所有脚本全部运行完成后,才输出,因为数据未满一个buffer的大小。

b、output_buffering=4096,输出较少的数据(少于一个buffer),关闭output_buffering,修改php.ini的output_buffering=0

echo str_repeat(" ",1024);//这里重复输出一个空白
for($i=0; $i<5; $i++){ 
echo $i."<br/>";
  flush(); 
  sleep(1); 
}

运行结果:因为禁用了OB,不需要等到脚本运行完毕就可以输出,数据没有在OB停留,可以看到断断续续间歇性输出。echo ->browser buffering -> browser display

c、output_buffering=4096,输出较大数据(大于一个buffer),不使用ob_start()

for($i=0; $i<5; $i++){ 
  echo file_get_contents('f.txt').$i.'<br/><br/><br/><br/>'; 
  sleep(2); 
}

运行结果:f.txt为一个大于4kb的文件,因为大于buffer默认值,buffer空间不够用,每当满一个buffer就会输出,所以可以看到间歇性输出。

d、output_buffering=4096,输出较大数据(大于一个buffer),使用ob_start()

ob_start(); 
for($i=0; $i<5; $i++){ 
  echo file_get_contents('f.txt').$i.'<br/><br/><br/><br/>'; 
  sleep(2); 
}

运行结果:因为使用了ob_start(),会为buffer设置足够大的空间,因此会保存到脚本执行完毕后才会输出。

e、output_buffering=On,使用ob_start()

ob_start();
echo "abc-";
header("content-type:text/html;charset=utf-8");
echo "hello-";
ob_end_flush();
echo "aa-";
echo ob_get_contents();

运行结果:abc-hello-aa-abc-hello-aa-

f、output_buffering=Off,使用ob_start()

ob_start();
echo "abc-";
header("content-type:text/html;charset=utf-8");
echo "hello-";
ob_end_flush();
echo "aa-";
echo ob_get_contents();

运行结果:abc-hello-aa-

输出缓冲区是可堆叠的,这即意谓着,当有一个 ob_start() 是活跃的时, 你可以调用另一个 ob_start() 。 只要确保又正确调用了 ob_end_flush() 恰当的次数即可。 如果有多重输出回调函数是活跃的,输出内容会一直按嵌套的顺序依次通过它们而被过滤。

注意:PHP5.2中,OB默认是关闭的,5.3之后默认是开启的;

常用方法:

1.ob_start
激活output_buffering机制,一旦激活,脚本不再直接输出到浏览器,而是暂时写入php buffering区域。直到脚本运行完毕后,才发送。

2.ob_get_contents
获取php buffering中的数据,注意:要在ob_end_clean()前调用,否则只会得到空字符。

3.ob_end_flush 和 ob_end_clean
ob_end_flush 会输出php buffering 中的数据,但不会清空。
ob_end_clean 不会输出,只会清空php buffering中的数据。

4.ob_flush 、flush、ob_implicit_flush
ob_flush 会刷新php buffering 中的数据到程序缓存

flush 则会刷新程序缓存到浏览器缓存中

ob_implicit_flush 将打开或关闭绝对(隐式)刷送。绝对(隐式)刷送将导致在每次输出调用后有一次刷送操作,以便不再需要对 flush() 的显式调用

四、OB缓存的作用!

OB缓存在各个方面都有应用,但是,本人知道的主要是在两个方面!
a、当网站准备做网站静态化的时候,选择OB缓存是一个不错的选择!

b、解决Warning: Cannot modify header information - headers already sent by的错误!
究其发生错误的原因:是因为响应头和相应主体位置错位导致的!正常情况下,服务器返回给浏览器的相应内容,应该是:响应头+响应主体!

但是,如果我们开启了OB缓存,那么相应头信息(一般也就是header()函数进行设置的信息),会被放入到程序缓存中!
而其他的输出内容,如:echo print_r var_dump 等,都会先被放入OB缓存中!
等程序结束的时候,或者OB缓存关闭的实话,将OB缓存的内容在放入程序缓存中!从而保证响应头信息,始终在响应主体内容之前!

以上所述就是本文的全部内容了,希望大家能够喜欢。

PHP 相关文章推荐
IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2009年
Jun 08 PHP
ThinkPHP上使用多说评论插件的方法
Oct 31 PHP
PHP类的反射用法实例
Nov 03 PHP
php打印一个边长为N的实心和空心菱型的方法
Mar 02 PHP
php从数据库查询结果生成树形列表的方法
Apr 17 PHP
smarty高级特性之过滤器的使用方法
Dec 25 PHP
PHP编程中尝试程序并发的几种方式总结
Mar 21 PHP
php利用ob_start()清除输出和选择性输出的方法
Jan 18 PHP
php基于Redis消息队列实现的消息推送的方法
Nov 28 PHP
PDO::_construct讲解
Jan 27 PHP
PHP 扩展Memcached命令用法实例总结
Jun 04 PHP
ThinkPHP6.0如何利用自定义验证规则规范的实现登陆
Dec 16 PHP
php实现模拟post请求用法实例
Jul 11 #PHP
php实现源代码加密的方法
Jul 11 #PHP
PHP数组操作类实例
Jul 11 #PHP
PHP实现事件机制的方法
Jul 10 #PHP
php目录拷贝实现方法
Jul 10 #PHP
php通过前序遍历树实现无需递归的无限极分类
Jul 10 #PHP
php中array_multisort对多维数组排序的方法
Jun 21 #PHP
You might like
Thinkphp3.2.3整合phpqrcode生成带logo的二维码
2016/07/21 PHP
基于jQuery的为attr添加id title等效果的实现代码
2011/04/20 Javascript
JQuery扩展插件Validate 2通过参数设置验证规则
2011/09/05 Javascript
easyui datagrid 键盘上下控制选中行示例
2014/03/31 Javascript
js动态改变select选择变更option的index值示例
2014/07/10 Javascript
JavaScript中的值类型转换介绍
2014/12/31 Javascript
Javascript基础教程之定义和调用函数
2015/01/18 Javascript
js实现仿百度汽车频道选择汽车图片展示实例
2015/05/06 Javascript
jquery插件NProgress.js制作网页加载进度条
2015/06/05 Javascript
javascript数组去重的六种方法汇总
2015/08/16 Javascript
input点击后placeholder中的提示消息消失
2016/01/15 Javascript
BootStrap栅格系统、表单样式与按钮样式源码解析
2017/01/20 Javascript
JS FormData上传文件的设置方法
2017/07/05 Javascript
vue axios用法教程详解
2017/07/23 Javascript
nodejs 图片预览和上传的示例代码
2017/09/30 NodeJs
JavaScript callback回调函数用法实例分析
2018/05/08 Javascript
React.js绑定this的5种方法(小结)
2018/06/05 Javascript
typescript nodejs 依赖注入实现方法代码详解
2019/07/21 NodeJs
非常实用的jQuery代码段集锦【检测浏览器、滚动、复制、淡入淡出等】
2019/08/08 jQuery
bootstrap table实现iview固定列的效果实例代码详解
2019/09/30 Javascript
js+html+css实现手动轮播和自动轮播
2020/12/30 Javascript
[03:42]2014DOTA2国际邀请赛 第三日比赛排位扑朔迷离
2014/07/12 DOTA
跟老齐学Python之list和str比较
2014/09/20 Python
Python遍历zip文件输出名称时出现乱码问题的解决方法
2015/04/08 Python
Linux RedHat下安装Python2.7开发环境
2017/05/20 Python
Python生成数字图片代码分享
2017/10/31 Python
python实现跨excel的工作表sheet之间的复制方法
2018/05/03 Python
python cookie反爬处理的实现
2020/11/01 Python
python用opencv 图像傅里叶变换
2021/01/04 Python
amazeui模态框弹出后立马消失并刷新页面
2020/08/19 HTML / CSS
韩语专业本科生求职信
2013/10/01 职场文书
大学生实习期自我评价范文
2013/10/03 职场文书
咖啡蛋糕店创业计划书
2014/01/28 职场文书
采购主管岗位职责
2014/02/01 职场文书
工作失职检讨书(精华篇)
2014/10/15 职场文书
高中政治教师教学反思
2016/02/23 职场文书