缓冲控制
对于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()

浙公网安备 33010602011771号