诡异的php 输出缓冲

时间:2024-09-29 14:34:20

我的本地环境 windows + apche + php5.2

今天,碰到一个诡异的问题,以前认为  php 脚本中调用 heade()函数之前不能有任何的如 echo,print ,print_r,var_dump等输出,否则的话就会报错。

但是,

<?php
header( 'Expires: Mon, 26 Jul 1998 05:00:00 GMT' );
echo "Expires: Mon, 26 Jul 1998 05:00:00 ;"; header( 'Expires: Mon, 26 Jul 1978 05:00:00 GMT' );

想上面这样,浏览器访问,执行脚本,没有报错。(本以为汇报这样的错误:Warning: Cannot modify header information - headers already sent by)

此事何解:???

方法:

打开浏览器的调试控制台,发现 HTTP response header 中的Exipres 为 1978,顿时明白了。

联想到php 的输出缓冲的问题,在php 的配置文件中,有这么一段,看最后一句

; Output buffering is a mechanism for controlling how much output data
; (excluding headers and cookies) PHP should keep internally before pushing that
; data to the client. If your application's output exceeds this setting, PHP
; will send that data in chunks of roughly the size you specify.
; Turning on this setting and managing its maximum buffer size can yield some
; interesting side-effects depending on your application and web server.
; You may be able to send headers and cookies after you've already sent output
; through print or echo. You also may see performance benefits if your server is
; emitting less packets due to buffered output versus PHP streaming the output
; as it gets it. On production servers, 4096 bytes is a good setting for performance
; reasons.
; Note: Output buffering can also be controlled via Output Buffering Control
; functions.
; Possible Values:
; On = Enabled and buffer is unlimited. (Use with caution)
; Off = Disabled
; Integer = Enables the buffer and sets its maximum size in bytes.
; Note: This directive is hardcoded to Off for the CLI SAPI
; Default Value: Off
; Development Value: 4096
; Production Value: 4096
; http://php.net/output-buffering
output_buffering = 4096

4K字节的缓冲,这意味着  前面的这两个输出

header( 'Expires: Mon, 26 Jul 1998 05:00:00 GMT' );
echo "Expires: Mon, 26 Jul 1998 05:00:00 ;";

还缓冲在服务器中(我的是apache服务器,nginx服务器有是怎么样子呢,这个还不知道。。。),还没有通过http输出到浏览器,因此,后面的

header( 'Expires: Mon, 26 Jul 1978 05:00:00 GMT' );这个输出呢,就把缓冲区中的 响应头修改为了 1978。

另外:
  1、如果输出达到 4096(4k)字节时,服务器会立即将缓冲区中的内容 flush 出来,即立即输出给浏览器。
  2、关于缓冲区处理的一些列函数,php提供了 ob_flush(), ob_get_contents()等一系列函数 还有一点:当我们不确定 缓冲区中的内容是否已经有输出,那怎么办呢?
php 内置的函数 headers_sent() 可以用来判断,一些框架 如cakephp中就是这个来检查的!!
if (!headers_sent()) {
 header( 'Expires: Mon, 26 Jul 1978 05:00:00 GMT' ); }
这样就可以了,就确保不会报这样子的错 Warning: Cannot modify header information - headers already sent by