结合php ob函数理解缓冲机制

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

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

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

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

  echo、print_r=>php output_buffering=>webServer buffer=>browser buffer=>browser display 小程序

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

  未使用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,脚本执行完毕。不少小程序输出内容没那么多,总不能等到缓冲区满了再输出吧~这一点再天然不过。ide

  使用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手册 ,里面会有详细的解释。本文列出了笔者开始并非很理解的一些函数,固然从此还会有新的问题出现,想到问题而且解决问题,生活的乐趣也许就在此处吧。

相关文章
相关标签/搜索