php中ob函数缓冲机制深入理解


Posted in PHP onAugust 03, 2015

下面就php中ob函数缓冲机制通过文字说明加代码分析的形式给大家展示如下:

对于一个刚刚入门的php程序员来说,php缓冲区是几乎透明的。在他们心目中,一个echo print_r 函数,数据便会‘嗖'的一声飞到浏览器上,显示出来。我也一直如此单纯地认为。 其实,在技术的世界里,向来都是由简单到复杂,也许那些技术开发者开始单纯如你我,但是面对残酷的现实,不得不调整策略,以期提高机器运行效率,最后想到了那些让我们赞叹的idea。

说到缓冲,也就是buffer,这里必须要和缓存做一下比较,单纯地比较定义是无意义的,莫不如看看它们做什么。缓存解决的是如何快速查找利用数据,节省cpu消耗问题,而缓冲解决的是高速cpu与低速I/O设备不匹配的问题。

再说下本文的另一个主角,ob函数,ob是output_buffering的简写。既然ob函数是php扩展函数,那么ob函数主要操作的也就是php buffer了。

简单说完本文两个主角,我们还必须回归开头的主题,echo print_r函数输出的数据是怎么到达浏览器让用户看到的呢?实际上的历程是这样的:

echo、print_r=>php output_buffering=>webServer buffer=>browser buffer=>browser display

我们可以清楚地看到,从echo、print_r函数到发送信息给客户端经历了两个缓冲区,在客户端还经历了一个浏览器缓冲区。我们本文主要讨论的是php output_buffering

未使用ob函数时缓冲区的使用情况

 

我们的代码很多时候是根本不使用ob函数的,那么它们使用缓冲区了吗?这要看php设置情况。缓冲区是通过php.ini中的output_buffering变量控制的。其默认值是off,可以设置为on来打开buffer。打来buffer后,即便程序中没有用ob函数,实际上代码也是使用了缓冲区的。另外,不管php.ini中output_buffering的设置,cli模式下的php始终默认是关闭的。

为什么要是缓冲区呢?简单来说,高速的cpu早早处理完自己的数据,想通过线路传递给用户,但是线路太窄了,一下输送不过去。如果引入缓冲区,cpu可以将快速将生成的数据放入缓冲区,然后自己哪儿凉快儿哪儿呆着这歇着去了。缓冲区根据指令适时将数据输出。这个样就合理解决了高速cpu与低速I/O设备的矛盾了。 

缓冲区的数据什么时候输出呢?1,当缓冲区满了的时候,缓冲是有容量大小的,到达极限则会自动输出内容。2,脚本执行完毕。很多小程序输出内容没那么多,总不能等到缓冲区满了再输出吧~这一点再自然不过。

使用ob函数时缓冲区的使用情况

 ob_start()

打开输出缓冲。这个函数是我们调用最多的一个函数之一。在output_buffering设置为on或者x k的情况下,这个函数与其说是打开输出缓冲,还不如说将输出缓冲扩充到很大。当然在output_buffering设置为off的条件下,ob_start会起到打开buffer的作用。ob_start()还可以传递一个可选参数 output_callback 函数,php官方手册有详细说明。

ob_get_contents()

只是得到输出缓冲区的内容,但不清除它。

ob_end_clean()与ob_clean()

这两个函数从字面意思上就可以看出其区别。前者清除缓冲区内容并且关闭,后者仅仅是做清除工作。需要注意的是,使用了这两个函数,在前面使用了echo、print_r等函数不会输出内容。

笔者曾经试图通过print_r打印出ob_get_contents()的内容,然后调用ob_clean()清除缓冲区,以免影响后面对缓冲区的操作,屡屡失败。仔细想想,print_r的内容再次写入缓冲区,而后面做了ob_clean()的操作,自然不会有任何输出。在ob_clean操作之前调用ob_flush()函数便可达到预想的效果。

ob_flush()与flush()

ob_flush()送出缓冲区的内容并且丢弃内容。因而在此函数之前最好采用ob_get_contents()获得缓冲区内容。flush()刷出服务器端缓冲,并且发往客户端。因而从流程上来说,应该是先调用ob_flush()而后再调用flush函数。

另外说明下再Apache buffer flush()的工作原理:在apache module的sapi下,flush会通过调用sapi_module()的flush成员函数指针,间接使用apache的api::ap_rflush刷新apache的输出缓冲区。当然apache其他模块比如mod_gzip可能改变这个动作的结果,可能自己进行输出缓冲区,这将导致flush()函数产生的结果不会立即被送到客户端浏览器。

ob_get_clean()

如果你已经熟练掌握ob_get_contents()ob_clean(),那这个函数就很简单了。因为它是前两者的结合体。它主要是得到当前缓冲区的内容并删除当前输出缓冲区。

ob函数还有很多,但大部分用法比较简单,理解较为容易。大家可以参照php手册 ,里面会有详细的解释。本文列出了笔者开始并不是很理解的一些函数,当然今后还会有新的问题出现,想到问题并且解决问题,生活的乐趣也许就在此处吧。

以上内容就是本文针对php中ob函数缓冲机制深入理解,希望对大家今后学习有所帮助。

PHP 相关文章推荐
php 定界符格式引起的错误
May 24 PHP
匹配csdn用户数据库与官方用户的重合度并将重叠部分的用户筛选出来
Dec 25 PHP
php stripslashes和addslashes的区别
Feb 03 PHP
CI使用Tank Auth转移数据库导致密码用户错误的解决办法
Jun 12 PHP
php浏览历史记录的方法
Mar 10 PHP
php中注册器模式类用法实例分析
Nov 03 PHP
php+jQuery递归调用POST循环请求示例
Oct 14 PHP
Thinkphp事务操作实例(推荐)
Apr 01 PHP
PHP下载远程图片的几种方法总结
Apr 07 PHP
php常用日期时间函数实例小结
Jul 04 PHP
Laravel框架中集成MongoDB和使用详解
Oct 17 PHP
php多进程并发编程防止出现僵尸进程的方法分析
Feb 28 PHP
如何利用http协议发布博客园博文评论
Aug 03 #PHP
在CentOS上搭建LAMP+vsftpd环境的简单指南
Aug 01 #PHP
如何使用php实现评委评分器
Jul 31 #PHP
php给图片加文字水印
Jul 31 #PHP
初识通用数据库操作类――前端easyui-datagrid,form(php)
Jul 31 #PHP
使用Appcan客户端自动更新PHP版本号(全)
Jul 31 #PHP
php使用Imagick生成图片的方法
Jul 31 #PHP
You might like
PHP页面转UTF-8中文编码乱码的解决办法
2015/10/20 PHP
Thinkphp5+Redis实现商品秒杀代码实例讲解
2020/12/29 PHP
jQuery 剧场版 你必须知道的javascript
2009/05/27 Javascript
JQuery 常用操作代码
2010/03/14 Javascript
js 幻灯片的实现
2011/12/06 Javascript
NodeJS 模块开发及发布详解分享
2012/03/07 NodeJs
jQuery函数的等价原生函数代码示例
2013/05/27 Javascript
JS实现根据出生年月计算年龄
2014/01/10 Javascript
AngularGauge 属性解析详解
2016/09/06 Javascript
浅谈jquery选择器 :first与:first-child的区别
2016/11/20 Javascript
利用Ionic2 + angular4实现一个地区选择组件
2017/07/27 Javascript
vue实现移动端图片裁剪上传功能
2020/08/18 Javascript
nodejs socket服务端和客户端简单通信功能
2017/09/14 NodeJs
nodejs实现爬取网站图片功能
2017/12/14 NodeJs
webpack组织模块打包Library的原理及实现
2018/03/10 Javascript
详解如何解决vue开发请求数据跨域的问题(基于浏览器的配置解决)
2018/11/12 Javascript
mpvue全局引入sass文件的方法步骤
2019/03/06 Javascript
详解小程序用户登录状态检查与更新实例
2019/05/15 Javascript
vue实现购物车列表
2020/06/30 Javascript
python中django框架通过正则搜索页面上email地址的方法
2015/03/21 Python
Python实现将目录中TXT合并成一个大TXT文件的方法
2015/07/15 Python
教你用python3根据关键词爬取百度百科的内容
2016/08/18 Python
Python中的默认参数实例分析
2018/01/29 Python
python PyTorch参数初始化和Finetune
2018/02/11 Python
windows7 32、64位下python爬虫框架scrapy环境的搭建方法
2018/11/29 Python
Python线程指南分享
2019/11/19 Python
Numpy将二维数组添加到空数组的实现
2019/12/05 Python
三个python爬虫项目实例代码
2019/12/28 Python
解决jupyter notebook 前面书写后面内容消失的问题
2020/04/13 Python
python输出数学符号实例
2020/05/11 Python
瑞典手机壳品牌:Richmond & Finch
2018/04/28 全球购物
向全球直邮输送天然健康产品:iHerb.com
2020/05/03 全球购物
机械专业毕业生自我鉴定2014
2014/10/04 职场文书
热血教师观后感
2015/06/10 职场文书
《哪吒之魔童降世》观后感:世上哪有随随便便的成功
2019/11/08 职场文书
CSS实现渐变色边框(Gradient borders)的5种方法
2022/03/25 HTML / CSS