Cannot modify header information - headers already sent by... 通过hader函数的报错学习输出缓冲区output_buffering
php,使用header函数时,
echo 'a';
header("content-type:text/html;charset=utf-8");
报错:Cannot modify header information - headers already sent byxxx
为啥呢
看手册中这样提醒的
请注意 header() 必须在任何实际输出之前调用,不管是普通的 HTML 标签,还是文件或 PHP 输出的空行,空格。这是个常见的错误,在通过 include , require ,或者其访问其他文件里面的函数的时候,如果在 header() 被调用之前,其中有空格或者空行。 同样的问题也存在于单独的 PHP/HTML 文件中。
解决的方案就是打开输出缓冲(outer_buffering),以下是php.ini中的描述:
; 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 = Off
该选项设置为 On 时,将在所有的脚本中使用输出控制。如果要限制输出缓冲区的最大值,可将该选项设定为指定的最大字节数(例如 output_buffering=4096)。
打开后,要输出的内容会放在缓冲区,这时,我上面的例子就不会报错了
光打开是不够的,我们还需要设置输出缓冲区的最大值,因为如果我输出的内容超过了限定值,仍然会在header之前输出,
所以我的建议是,在php.ini中设置一个最大值(官方建议4096),然后利用ob_start函数去灵活配置
ob_start — 打开输出控制缓冲
此函数将打开输出缓冲。当输出缓冲激活后,脚本将不会输出内容(除http标头外),相反需要输出的内容被存储在内部缓冲区中。
bool ob_start ([ callback $output_callback
[, int $chunk_size
[, bool $erase
]]] )
注意上面的第二个可选参数,chunk_size,
如果可选参数 chunk_size
被赋值了,在任何一个能引起缓冲区的长度等于 或超过 chunk_size
的输出操作后,缓冲区都会被刷送。 默认值 0 意味着函数仅在最后被调用,其余的特殊值可以将 chunk_size
从 1 设定到 4096。
我们也不知道我们输出的内容会有多大,所以,一般是采取默认值0。
输出缓冲区是可堆叠的,这即意谓着,当有一个 ob_start() 是活跃的时, 你可以调用另一个 ob_start() 。 只要确保又正确调用了 ob_end_flush() 恰当的次数即可。 如果有多重输出回调函数是活跃的,输出内容会一直按嵌套的顺序依次通过它们而被过滤。
如果获取缓冲区的内容,可以使用 ob_get_flush 刷出(送出)缓冲区内容,以字符串形式返回内容,并关闭输出缓冲区。
做个总结:
我们可以将要输出的内容暂放在缓冲区,至于怎么用,完全看我们自己,输出缓冲的用途
1.防止使用print/echo等函数输出内容时,输出响应头的函数报错,如上例的header,还有session相关,cookie相关,都可以避免输出响应头之前输出了其他内容.
2.实现页面静态化,因为ob_get_flush可以获取页面内容,我们可以把输出保存成文件.