浅谈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 相关文章推荐
超级简单的发送邮件程序
Oct 09 PHP
WIN98下Apache1.3.14+PHP4.0.4的安装
Oct 09 PHP
常用表单验证类,有了这个,一般的验证就都齐了。
Dec 06 PHP
缓存技术详谈―php
Dec 14 PHP
一个用php实现的获取URL信息的类
Jan 02 PHP
使用PHP实现密保卡功能实现代码&amp;lt;打包下载直接运行&amp;gt;
Oct 09 PHP
php 地区分类排序算法
Jul 01 PHP
PHP中soap的用法实例
Oct 24 PHP
php使用ZipArchive函数实现文件的压缩与解压缩
Oct 27 PHP
php制作简单模版引擎
Apr 07 PHP
PHP命名空间namespace用法实例分析
Sep 27 PHP
Yii框架 session 数据库存储操作方法示例
Nov 18 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
深入了解PHP类Class的概念
2012/06/14 PHP
php限制上传文件类型并保存上传文件的方法
2015/03/13 PHP
PHP 7.1中AES加解密方法mcrypt_module_open()的替换方案
2017/10/17 PHP
PHP反射原理与用法深入分析
2019/09/28 PHP
laravel5.6 框架操作数据 Eloquent ORM用法示例
2020/01/26 PHP
使用jquery自定义鼠标样式满足个性需求
2013/11/05 Javascript
自己使用js/jquery写的一个定制对话框控件
2014/05/02 Javascript
JS获取及设置TextArea或input文本框选择文本位置的方法
2015/03/24 Javascript
JavaScript中函数(Function)的apply与call理解
2015/07/08 Javascript
js实现拉幕效果的广告代码
2015/09/02 Javascript
js实现tab切换效果实例
2015/09/16 Javascript
纯JavaScript代码实现移动设备绘图解锁
2015/10/16 Javascript
使用JQuery实现的分页插件分享
2015/11/05 Javascript
js控件Kindeditor实现图片自动上传功能
2020/07/20 Javascript
Javascript将字符串日期格式化为yyyy-mm-dd的方法
2016/10/27 Javascript
vue mixins组件复用的几种方式(小结)
2017/09/06 Javascript
在React项目中使用Eslint代码检查工具及常见问题
2018/10/10 Javascript
JS实现基本的网页计算器功能示例
2020/01/16 Javascript
vue使用echarts实现水平柱形图实例
2020/09/09 Javascript
[05:05]DOTA2亚洲邀请赛 战队出场仪式
2015/02/07 DOTA
[01:17:47]TNC vs VGJ.S 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Flask框架的学习指南之用户登录管理
2016/11/20 Python
解决pycharm界面不能显示中文的问题
2018/05/23 Python
django模板加载静态文件的方法步骤
2019/03/01 Python
Django Docker容器化部署之Django-Docker本地部署
2019/10/09 Python
python通过SSH登陆linux并操作的实现
2019/10/10 Python
Selenium Webdriver元素定位的八种常用方式(小结)
2021/01/13 Python
中专毕业个人的自荐信格式
2013/09/21 职场文书
运动会入场解说词
2014/02/07 职场文书
中央空调节能方案
2014/06/15 职场文书
2014年学校领导班子对照检查材料
2014/09/19 职场文书
党委领导班子整改方案
2014/09/30 职场文书
《去年的树》教学反思
2016/02/18 职场文书
vue3如何优雅的实现移动端登录注册模块
2021/03/29 Vue.js
浅谈自定义校验注解ConstraintValidator
2021/06/30 Java/Android
python机器学习创建基于规则聊天机器人过程示例详解
2021/11/02 Python