说到输出缓冲,首先要说的是一个叫做缓冲器(buffer)的东西。举个简单的例子说明他的作用:我们在编辑一篇文档时,在我们没有保存之前,系统是不会向磁盘写入的,而是写到buffer中,当buffer写满或者执行了保存操作,才会将数据写入磁盘。对于PHP来说,每一次像 echo 这样的输出操作,同样是先写入到了 php buffer 里,在脚本执行完毕或者执行了强制输出缓存操作,数据才会在浏览器上显示。
其实对于PHP程序员来说,基本上每个脚本都涉及到了输出缓冲,只是在大多数情况下,我们都不需要对输出缓冲进行更改。而今天就来用实例对PHP输出缓冲控制函数“Output Control”做一个详细的解析。
下面这个例子简单介绍了输出缓冲在一般脚本中存在的方式:
我们在执行如下脚本时:
123456 | <?php /*例1*/ echo 'oschina.net' ; echo '红薯' ; echo '虫虫' ; ?> |
脚本在执行完第一个 echo 时,并不会向浏览器输出相应内容,而是会输出到一个缓冲区,依次类推,当三个 echo 全部执行完毕(也就是脚本结束)时,才会将缓冲区内容全部输出到浏览器。当然这个缓冲区也有大小的限制,是根据 php.ini 中的output_buffering
选项来设置的,这点会在下面的文章中详细介绍。而本章所讲的输出缓冲控制,就是在脚本结束前,对缓冲区里的内容进行操作。
这个例子可以更好的体现输出缓冲控制的应用:
在执行如下代码时:
12345678 | <?php /*例2*/ echo 'oschina.net' ; sleep(1); echo '红薯' ; sleep(1); echo '虫虫' ; ?> |
我们至少需要等待 2秒 才能看到输出结果,那我们能不能让其实时的显示呢?也就是在第一个 echo 执行完毕时就输出相应的内容呢,这时候就需要用输出缓冲控制函数来操作缓冲区了,实现代码如下:
123456789101112131415 | <?php /*例3*/ echo str_pad ( '' , 1024); //使缓冲区溢出 ob_start(); //打开缓冲区 echo 'oschina.net' ; ob_flush(); //送出当前缓冲内容,不会输出 flush (); //输出送出的缓冲内容 sleep(1); echo '红薯' ; ob_flush(); //送出当前缓冲内容,不会输出 flush (); //输出送出的缓冲内容 sleep(1); echo '虫虫' ; ob_end_flush(); //输出并关闭缓冲 ?> |
简单点也可以这样实现:
1234567891011 | <?php /*例4*/ echo str_pad ( '' , 1024); //使缓冲区溢出 echo 'oschina.net' ; flush (); //输出送出的缓冲内容 sleep(1); echo '红薯' ; flush (); //输出送出的缓冲内容 sleep(1); echo '虫虫' ; ?> |
至于相关函数的用法在下面都会有介绍,这里只是给大家展示一个输出缓冲控制函数的应用,当然了输出缓冲控制函数的作用绝不止这一种,那么下面我们就来看看输出缓冲控制函数都可以应用在哪些方面。
作用 再来看看在 php.ini 中和输出缓冲控制有关的选项,共三个,分别是:output_buffering
,output_handler
和implicit_flush
output_buffering
默认为 off , 当设置为 on 时,则在所有脚本自动打开输出缓冲区,拿 例3 来说,就是在每个脚本都自动执行了 ob_start() 这个函数,而不用再显示的调用该函数。其也可以设置为一个整型的数字,代表缓冲区可以存储的最大字节数,我们在 例1 的下面说明中提到过这个配置项。output_handler
默认为 null , 其值只能设置为一个内置的函数名,作用就是将脚本的所有输出,用所定义的函数进行处理。他的用法和 ob_start('function_name') 较类似,下面会介绍到。implicit_flush
默认为 off , 当设置为 on 时,PHP将在输出后,自动送出缓冲区内容。拿 例4 来说,就是在每段输出后,自动执行 flush() 。当然有效的输出不仅指像echo , PRint 这样的函数,也包括HTML段。现在我们就用实例分析相关函数,相信在充分了解了以下内容后,就会对输出缓冲控制函数有了较清晰的掌握。
1. bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
此函数在 例3 中已经使用过,大家从命名上也能明白其含义,就是打开输出缓冲区,从而进行下一步的输出缓冲处理。这里要特意说的是其参数的用法,第一个参数要传递一个回调函数,其需将缓冲区内容做为参数,并且返回一个字符串。他会在缓冲区被送出时调用,缓冲区送出指的是执行了例如ob_flush() 等函数或者脚本执行完毕。ob_flush() 函数会在下面介绍到,来看一个简单的例子就能理解其用法:
123456789 | <?php /*例5*/ ob_start( 'handleString' ); echo '123456' ;
function handleString( $string ){
return md5( $string ); } ?> |
运行后的结果是:
1 | e10adc3949ba59abbe56e057f20f883e |
说明输出的内容被md5加密了,也就是说在缓冲区内容输出时,运行了我们定义的 handleString 函数。
再来看一个更实际的例子,也就是常见到的将网页内容利用 gzip 压缩后再输出,代码如下:
12345 | <?php /*例6*/ ob_start( 'ob_gzhandler' ); echo str_repeat ( 'oschina' , 1024); ?> |
其页面大小为:
而不使用 ob_gzhandler 参数,其页面大小为: