5ucms论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 6561|回复: 0
打印 上一主题 下一主题

[基础] PHP的输出缓冲区从入门到精通教程

[复制链接]

670

主题

785

帖子

8228

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
8228
跳转到指定楼层
楼主
发表于 2017-5-30 07:26:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
当我们使用php里面的echo、print_r等打印输出命令时,如果写的代码是正确的话会立马看到结果,例如,在文件5ucms.php里面编写如下代码:

  1. <?php
  2. header('content-type: text/html;charset=utf-8');
  3. echo "邱嵩松技术论坛bbs.5ucms.com";
复制代码


就会在浏览器窗口中输出
  1. 邱嵩松技术论坛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请求了,否则程序会提示错误:
  1. Cannot modify header information – headers already sent by;
复制代码


例如:

  1. <?php
  2. echo "邱嵩松技术论坛bbs.5ucms.com";
  3. header('content-type: text/html;charset=utf-8');
  4. 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缓冲区相关的函数

  1. flush — 刷新输出缓冲
  2. ob_clean — 清空(擦掉)输出缓冲区
  3. ob_end_clean — 清空(擦除)缓冲区并关闭输出缓冲
  4. ob_end_flush — 冲刷出(送出)输出缓冲区内容并关闭缓冲
  5. ob_flush — 冲刷出(送出)输出缓冲区中的内容
  6. ob_get_clean — 得到当前缓冲区的内容并删除当前输出缓。
  7. ob_get_contents — 返回输出缓冲区的内容
  8. ob_get_flush — 刷出(送出)缓冲区内容,以字符串形式返回内容,并关闭输出缓冲区。
  9. ob_get_length — 返回输出缓冲区内容的长度
  10. ob_get_level — 返回输出缓冲机制的嵌套级别
  11. ob_get_status — 得到所有输出缓冲区的状态
  12. ob_gzhandler — 在ob_start中使用的用来压缩输出缓冲区中内容的回调函数。ob_start callback function to gzip output buffer
  13. ob_implicit_flush — 打开/关闭绝对刷送
  14. ob_list_handlers — 列出所有使用中的输出处理程序。
  15. ob_start — 打开输出控制缓冲
  16. output_add_rewrite_var — 添加URL重写器的值(Add URL rewriter values)
  17. 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进行输出。

代码如下:

  1. <?php
  2. ob_start();

  3. echo "腾讯网www.qq.com";
  4. header('content-type: text/html;charset=utf-8');

  5. ob_clean();

  6. echo "邱嵩松技术论坛bbs.5ucms.com";
  7. $contents = ob_get_contents();
  8. file_put_contents("d:/wamp/www/5ucms.log",$contents);
  9. 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,以此类推。

代码如下:

  1. echo str_repeat('',10240);

  2. for($i=1;$i<10;$i++) {
  3. echo $i;

  4. flush();
  5. sleep(1);
  6. }
复制代码


  这里使用了函数flush(),这个函的作用是刷新输出缓冲,有的公司用这个函数来处理类似像股票的实时数据的,只是我们建设网站一般很少用到。

  注意:一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。这就是为什么上面我们要使用str_repeat()函数输出一些空格的原因。

总结:

  1)若开启ob缓冲区,则echo 输出的数据首先放在ob缓冲区里面。

  2)如果是header信息,则把header信息放到程序缓冲区里面。

  3)无论开没有开启ob缓冲区,程序缓冲区一直是开启的。

  4)当页面执行到最后,如果没有输出代码了,则程序会把ob缓冲区的内容都放到程序缓冲区,然后,一并显示到浏览器。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|5ucms.com

GMT+8, 2024-4-19 12:42 , Processed in 0.437500 second(s), 32 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表