5ucms论坛
标题:
PHP的输出缓冲区从入门到精通教程
[打印本页]
作者:
admin
时间:
2017-5-30 07:26
标题:
PHP的输出缓冲区从入门到精通教程
当我们使用php里面的echo、print_r等打印输出命令时,如果写的代码是正确的话会立马看到结果,例如,在文件5ucms.php里面编写如下代码:
<?php
header('content-type: text/html;charset=utf-8');
echo "邱嵩松技术论坛bbs.5ucms.com";
复制代码
就会在浏览器窗口中输出
邱嵩松技术论坛bbs.5ucms.com
复制代码
这样的结果
这是非常好理解的,但是,
这个过程并不像我们看到的
,在浏览器打开这个文件5ucms.php后马上显示结果,其实,我们看到的与服务器执行程序时处理的过程是不一样的,服务器接收到请求,然后,把数据输出到浏览器之间有一个处理过程。
当浏览器向服务器发出http请求(即打开文件5ucms.php就是通过浏览器向服务器发出http请求)的过程如下:
1)首先要输出的头部header代码信息将被放到php内部缓冲区也就是“程序缓冲区”里面,然后,再把输出的内容“邱嵩松技术论坛bbs.5ucms.com”放到“ob缓冲”里面。
2)当5ucms.php文件里面的代码全部执行完后,服务器(例如apache)会把“ob缓冲”里面的内容放到“程序缓冲”里面。
3)最后,把“程序缓冲”里面的内容一下了全部输出到浏览器上面,这样我们就看到了输出的内容了。
ob缓冲区的开关
ob缓冲区是在php.ini文件里面由output_buffering的值决定是开还是关:
值为Off时: 表示关闭PHP输出缓存
值为On时: 打开无限大的输出缓存
如果关闭缓冲区的话,即output_buffering=Off,则http请求流程将变成:服务器会把所有的header请求和内容都先放到程序缓冲区中,然后,再把这些内容一并输出到浏览器。
注意:如果没有开启ob缓冲区的话,即output_buffering=Off,那么,在文件phpos.php里面编写代码时头部代码就不能与输出的信息顺序颠倒,否则会出错。这是因为输出内容时,通过浏览器发送了http请求放到了程序缓冲区,接下来你又发一个header请求这是不允许的,因为你已经发送http请求,发送后就不允许再去修改http请求了,否则程序会提示错误:
Cannot modify header information – headers already sent by;
复制代码
例如:
<?php
echo "邱嵩松技术论坛bbs.5ucms.com";
header('content-type: text/html;charset=utf-8');
echo "邱嵩松技术论坛bbs.5ucms.com";
复制代码
就会提示出错了
结论:如果您关闭了ob缓冲区,那么,您发送http请求(例如打开某个php文件)必须把header放在最前面,否则,在header前面的输出也会发一次请求,而后面也会发一次请求这样就会重复,程序以为我们要修改发第一次发送的http请求数据,所以,提示上面的错误。
开启ob缓存
当开启ob缓存后,header和输出的内容就不会有顺序上的问题,无论在header头部放不放输出代码都不会出错,这是因为输出内容是放在ob缓冲区的,而header的http请求则是在程序缓冲区的两者并不冲突。
当程序没有要输出的内容后,服务器会把ob缓冲区里面的内容放到“程序缓冲区”一起显示到浏览器里面。
ob缓冲区的作用
也许我们很少直接使用到ob缓冲区,那可能是因为我们很少进行深入的php开发,如果做高级php开发的话,会经常使用到ob缓冲。ob和程序缓冲区到底有什么作用,其实作用非常多,例如,假设您要通过http下载一个800M的视频,如何使用php进行开发,这就要用到ob缓冲区了,假设您想一下子下载下来那先把800M的视频保存到内存中,而php.ini总的memory_limit, 其默认值是8M,所以,不可能一下子读到内存中,也就是不能一下子下载下来,如果有ob内存则可以把800M分成一段一段的视频进行下载,然后,放到ob缓冲区内,这样就可以实现把800M视频下载下来了。
再举一个缓冲区的应用就是我们在设计网站时,需要设置生成的内容为静态,这时缓冲区就又要用到了,其实,缓冲区的用处非常多,只是我们一般人没有做这些非常底层的开发,所以,对这些没有太多感觉。
输出控制函数
上面无论是ob缓冲区还是程序缓冲区它们都是计算机内存里面的一块缓冲区域,这里面的内存是可以通过一系统php函数来操作的,例如,通过php函数打开缓冲区、把缓冲区的内容都强制放到程序缓冲区里等操作。
ob缓冲区相关的函数
flush — 刷新输出缓冲
ob_clean — 清空(擦掉)输出缓冲区
ob_end_clean — 清空(擦除)缓冲区并关闭输出缓冲
ob_end_flush — 冲刷出(送出)输出缓冲区内容并关闭缓冲
ob_flush — 冲刷出(送出)输出缓冲区中的内容
ob_get_clean — 得到当前缓冲区的内容并删除当前输出缓。
ob_get_contents — 返回输出缓冲区的内容
ob_get_flush — 刷出(送出)缓冲区内容,以字符串形式返回内容,并关闭输出缓冲区。
ob_get_length — 返回输出缓冲区内容的长度
ob_get_level — 返回输出缓冲机制的嵌套级别
ob_get_status — 得到所有输出缓冲区的状态
ob_gzhandler — 在ob_start中使用的用来压缩输出缓冲区中内容的回调函数。ob_start callback function to gzip output buffer
ob_implicit_flush — 打开/关闭绝对刷送
ob_list_handlers — 列出所有使用中的输出处理程序。
ob_start — 打开输出控制缓冲
output_add_rewrite_var — 添加URL重写器的值(Add URL rewriter values)
output_reset_rewrite_vars — 重设URL重写器的值(Reset URL rewriter values)
复制代码
ob缓冲函数使用方法
1)开启ob缓冲区:ob_start();
2)使用上面的函数处理自己的业务。
实例一
假设有三个网站分别是:邱嵩松技术论坛bbs.5ucms.com,百度网
www.baidu.com
,腾讯网
www.qq.com
。
开发要求:使用ob缓冲区技术把上面的微信网址保存到日志文件phpos.log里面,并把微信网址和百度网址显示出来,但是,不显示不保存腾讯网网址,必须使用echo进行输出。
代码如下:
<?php
ob_start();
echo "腾讯网www.qq.com";
header('content-type: text/html;charset=utf-8');
ob_clean();
echo "邱嵩松技术论坛bbs.5ucms.com";
$contents = ob_get_contents();
file_put_contents("d:/wamp/www/5ucms.log",$contents);
echo "百度www.baidu.com";
复制代码
代码分析:
先开启ob缓存,然后,输出腾讯网址,根据上面的原理腾讯网址保到了ob缓冲区,然后,把header头信息保存到“程序缓冲区”。
等执行到函数ob_clean()后,这个函数的作用是把ob缓冲区的内容全部清空,所以,这样就把腾讯网址从ob清理掉了。
然后,把微信网址放到ob缓冲区,然后,通过ob_get_contents()函数(这个函数类似获取文件内容函数file_get_contents())获取到ob缓冲区的内容,并通过函数file_put_contents()把内容保存到了日志文件5ucms.log里面。
最后,又把百度网址保存到ob缓冲区里面,然后,程序再向下执行代码发现没有要输出的内容了,于是,做最后一步“工作”把ob缓冲区的内容全部放到“程序缓冲区”,然后,一并显示到浏览器里面。
实例二
要求:把1到10的数值从零开始,每隔一秒输出一个数字。
这个要求是这样的:每过一秒就显示一个数值,数值从1开始,例如,刚开始显示1,过一秒后显示2,再过一秒后显示3,以此类推。
代码如下:
echo str_repeat('',10240);
for($i=1;$i<10;$i++) {
echo $i;
flush();
sleep(1);
}
复制代码
这里使用了函数flush(),这个函的作用是刷新输出缓冲,有的公司用这个函数来处理类似像股票的实时数据的,只是我们建设网站一般很少用到。
注意:一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。这就是为什么上面我们要使用str_repeat()函数输出一些空格的原因。
总结:
1)若开启ob缓冲区,则echo 输出的数据首先放在ob缓冲区里面。
2)如果是header信息,则把header信息放到程序缓冲区里面。
3)无论开没有开启ob缓冲区,程序缓冲区一直是开启的。
4)当页面执行到最后,如果没有输出代码了,则程序会把ob缓冲区的内容都放到程序缓冲区,然后,一并显示到浏览器。
欢迎光临 5ucms论坛 (http://bbs.5ucms.com/)
Powered by Discuz! X3.2