PHP基础之输出缓冲区基本概念、原理分析

Wesley13
• 阅读 503

一、概念

在PHP运行的过程中,可以将会产生输出的函数或操作结果暂时保存在PHP的缓冲区,只有当缓冲区满了、或者PHP运行完毕、或者在必要时候进行输出,才会将数据输出到浏览器,此缓冲数据的区域称为PHP的输出缓冲区(OB)。

二、原理

①使用了缓冲区之后,当执行PHP的时候,如果碰到了echo、print_r之类的会输出数据的代码(实际上许多函数都会产生输出),PHP就会将要输出的数据放到PHP自身的缓冲区,等待输出;

②当PHP自身的缓冲区接到指令,指示要输出缓冲区的内容时,将会把缓冲区内的数据输出到服务器上, 服务器接受到PHP输出的数据,然后再把该数据存在到服务器自身的缓冲区内,等到输出;

③当服务器接受到指令,只是要输出缓冲区的内容时, 将会把缓冲区的内容输出,返回到浏览器。

PHP基础之输出缓冲区基本概念、原理分析

上面可以看出,输出缓冲区层不是唯一用于缓冲输出的层,它实际上只是很多层中的一个。最后一点你要记住输出缓冲区层的行为跟你使用的SAPI(web或cli)相关,不同的SAPI可能有不同的行为。

第一点概念有提到,缓冲区满了会将缓冲数据输出,这个跟SAPI有关,缓冲区主要是通过php.ini中的output_buffering变量控制。output_buffering的默认是on,默认值是4096(4kb)。

三、输出缓冲区的配置

1、以我们通常使用的PHP-FPM这种SAPI为例,这里总结一下php的ini文件配置,主要为三个选项:

output_buffering
implicit_flush
output_handler

通过一个表格来理清一下这三个参数的含义:

PHP基础之输出缓冲区基本概念、原理分析

注意,以上三个值不能在运行时使用ini_set()改这几个选项的值。

2、关于PHP CLI方式执行时的配置,与FPM不太一样,有几点需要注意的是:

(1) output_buffering参数默认是不开启的,

(2) implicit_flush参数默认被置为1(开启)。

3、关于output_handler设置回调函数,可参考一下几个常用设置:

①ob_gzhandler : 使用ext/zlib压缩输出;

②mb_output_handler : 使用ext/mbstring转换字符编码;

③ob_iconv_handler : 使用ext/iconv转换字符编码;

④ob_tidyhandler : 使用ext/tidy整理输出的HTML文本;

⑤ob_[inflate/deflate]_handler : 使用ext/http压缩输出;

⑥ob_etaghandler : 使用ext/http自动生成HTTP的Etag;

四、输出缓冲区相关方法

ob_start();        //打开一个输出缓冲区,所有的输出信息不再直接发送到下一层,而是保存在输出缓冲区里面。
ob_clean();       //删除内部缓冲区的内容,不关闭缓冲区(不输出)。
ob_end_clean();   //删除内部缓冲区的内容,关闭缓冲区(不输出)。
ob_get_clean();   //返回内部缓冲区的内容,关闭缓冲区。
ob_flush();        //发送缓冲区内容到下一层,删除缓冲区内容,不关闭缓冲区。
ob_end_flush();    //发送缓冲区内容到下一层,删除缓冲区的内容,关闭缓冲区。
ob_get_flush();    //返回缓冲区的内容,并关闭缓冲区,再释放缓冲区的内容。
ob_get_contents();  //返回缓冲区的内容,不输出。
ob_get_length();    //返回缓冲区的长度,如果缓冲区未被激活,则返回FALSE。
ob_get_status() ;    //得到所有输出缓冲区的状态。
ob_implicit_flush();   //打开/关闭绝对刷送。

五、输出缓冲区的应用

1、在session、cookie、header等设置函数之前开启:

最常见的就是在使用header函数之前,就已经输出了某些数据,这样会导致某些错误,例如 Cannot modify header information – headers already sent by;

出现这个错误的原因是, 在header之前已经输出了某些数据,而输出这些数据的同时, 服务器将会同时发送一个响应状态到浏览器上(既然有输出,即这个请求是有效的),而其后你又再次使用header函数

发送http头,则会返回这个错误,错误的意思是:HTTP头已经发送出去了,你不能对他再做修改。

因此可以在开头先开启ob_start方法。

2、控制PHP程序的下载功能:

通常很多人会用PHP实现文件下载,但是当一个文件大小过大(例如100M)时,如果先全部读入内存再传送给用户,会导致响应时间大大加长(甚至超时),同时内存占用也会大大增加(甚至溢出)。

使用输出缓冲,可以将读取的文件读入缓冲区,达到一定大小时传送给用户,再继续读取,实现分片的效果。这样浏览器就可以持续地接受到数据,而不必等到所有文件读取完毕,同时内存也不会占用太大。

3、作为静态文件缓存:

将需要多次反复读取,并且求改频率很低的文件,第一次读取时放入缓冲区,生成静态文件,之后每次读取可以直接返回而不需要进过php的处理(读取数据库等)。

您可能感兴趣的文章:

文章同步发布: https://www.geek-share.com/detail/2771912063.html

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
PHP用proc_open新建子进程使用管道通信非阻塞执行PHP脚本
PHP用proc\_open新建子进程使用管道通信非阻塞执行PHP脚本.脚本结束时register\_shutdown\_function回调函数访问管道获取子进程输出的数据.例子1(popen):<?phpfunctionfoo(){echodate('YmdH:i:s')."\n";
Wesley13 Wesley13
2年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Stella981 Stella981
2年前
PHP全局变量与SESSION 漏洞(global 与 session)
先看这一段简单的代码<?phpsession\_start();$\_SESSION\‘isadmin’\’yes’;$isadmin’no’;echo$\_SESSION\‘isadmin’\;?当php.ini里配置register\_globalsOff时,没任何问题,输出yes但是当php.
Wesley13 Wesley13
2年前
PHP输出JSON,如何把空数组输出为对象
PHP输出JSON数据是非常方便的。一般情况下,PHP的一维数组输出为JSON时,会转成一个对象,也就是下面的形式:<?php$array'name''crazymus','age'18;echojson_encode($array
Stella981 Stella981
2年前
PHP+jQuery寥寥几行代码轻松实现百度搜索那样的无刷新PJAX的分页列表和导航链接
!(https://static.oschina.net/uploads/space/2016/1208/171419_U00R_561214.png)PHP寥寥几行代码轻松实现百度搜索那样的分页列表和导航链接,某些语言的拥趸哭晕在厕所.<?php$apparray('db_prefix''
Wesley13 Wesley13
2年前
DBMS_OUTPUT(用于输入和输出信息)
1、概述作用:用于输入和输出信息,使用过程PUT和PUT\_LINES可以将信息发送到缓冲区,使用过程GET\_LINE和GET\_LINES可以显示缓冲区信息。该包用来输出plsql变量的值,属于系统用户sys。下面讲述包的组成:2、包的组成1)、ENABLE说明:该过程用于激活本包,如果没
Wesley13 Wesley13
2年前
PHP中的NOW()函数
是否有一个PHP函数以与MySQL函数NOW()相同的格式返回日期和时间?我知道如何使用date()做到这一点,但是我问是否有一个仅用于此的函数。例如,返回:2009120100:00:001楼使用此功能:functiongetDatetimeNow(){