一: PHP header 函数
该函数发送原生 http 头。必须在任何实际输出之前调用,不管是普通的 html 标签,还是文件或PHP输出的空行、空格。
注意:header 函数之后的php代码仍然会被执行。
若是在 header 函数之前有内容输出,则产生如下警告:
Warning: Cannot modify header information - headers already sent by (output....)
// 示例一:
<html>asdf</html>
<?php
header('Location : http://segmentfault.com/');
// 示例二:
<?php
echo "html";
header('Location : http://segmentfault.com/');
但是,以上两个示例的代码并没有产生警告。原因是虽然使用了 html标签 或者 echo 输出函数,但是服务器会缓存内容,这些内容还没有作为 http 报文输出,这个时候仍有机会修改 HTTP 头。以下两个示例的代码会发出警告
// 示例三:
<?php
echo "<html></html>";
ob_flush();
flush();
header('Location: http://segmentfault.com/');
// 示例四:
<?php
for($i = 0; $i < 1e5; $i++) echo $i;
header('HTTP/1.1 200 OK');
二: PHP 控制输出 ob 函数
函数 | 作用 | 返回值 |
---|---|---|
flush | 刷新输出缓冲,将当前为止程序的所有输出发送到用户浏览器 | void |
ob_flush | 输出缓冲区中的内容,此函数不会销毁输出缓冲区 | void |
ob_end_flush | 输出缓冲区内容并关闭缓冲 | true / false |
ob_end_clean | 清空缓冲区并关闭缓冲 | true / false |
ob_start | 打开输出控制缓冲 | true / false |
查看以下示例:
// 示例一: 不会每隔1s输出 $i
<?php
for ($i=10; $i>0; $i--) {
echo $i;
flush();
sleep(1);
}
?>
// 示例二:添加 ob_end_clean() 或者 ob_end_flush() ,实现每隔1s输出$i
<?php
ob_end_clean();
for ($i=10; $i>0; $i--) {
echo $i;
flush();
sleep(1);
}
?>
// 示例三:添加 ob_flush() ,也实现了每隔1s输出$i
<?php
for ($i=10; $i>0; $i--) {
echo $i;
ob_flush();
flush();
sleep(1);
}
?>
原因分析:php.ini 文件中 output_buffering = 4096;// 该设置的作用就是把输出缓冲一下,缓冲大小为4096bytes。
示例一中就是因为输出不够 4096bytes 或者脚本未执行结束 ,所以输出是不会发送出去的
示例二中 ob_end_clean 与 ob_end_flush 作用都是终止缓冲。这样就不用等到 4096bytes才发送输出内容了
示例三中 ob_flush 的作用是把缓冲的数据发送出去,但是不会终止缓冲。它必须每次在 flush 之前调用,因为它只是释放出了缓冲区中的内容,而 flush 是将不在缓冲区中的输出或者说释放出来的数据发送到客户端浏览器。
若是不想调用 flush 以及 ob_flush ,可以设置ini文件中 output_buffering=0,不能用ini_set 设置,因为在脚本一开始的时候缓冲设置就已经被载入了。其次还可以采用以下两种方式
// ob_implicit_flush — 打开/关闭绝对刷送
<?php
ob_implicit_flush(true);
for($i=0;$i<10;$i++) {
echo $i;
ob_flush();
sleep(1);
}
// ob_end_clean 或者 ob_end_flush
<?php
ob_end_clean();
ob_implicit_flush(true);
for($i=0;$i<10;$i++) {
echo $i;
sleep(1);
}
ob_end_flush 与 ob_end_clean 的区别
// 多次打开、关闭缓冲区。注释掉一个ob_start后,最后一个ob_end_flush发出警告,类推
<?php
ob_start();
echo "A<br />";
ob_start();
echo "B<br />";
ob_start();
echo "C<br />";
ob_end_flush();
ob_end_flush();
ob_end_flush();
// 输出结果 A B C
<?php
ob_start();
echo "A<br />";
ob_start();
echo "B<br />";
ob_start();
echo "C<br />";
ob_end_clean(); // 清空缓冲区并关闭
ob_end_flush();
ob_end_flush();
// 输出结果 A B
<?php
ob_start();
echo "A<br />";
ob_start();
echo "B<br />";
ob_start();
echo "C<br />";
ob_end_clean();
ob_end_flush();
ob_end_clean();
// 输出结果 什么也不输出
此处面临多级缓冲机制。程序中有三个 ob_start 意味着有三个缓存区 A、B、C,PHP程序本身还有一个最终输出缓冲区F。这些缓冲区的层次为 C > B > A > F,F层次最高,是程序最终的输出缓冲区。
刚开始 F:null ——> ob_start();// 新建缓冲区A:null ——> echo "A<br />" // 输出进入缓冲区A ——> ob_start(); // 新建缓冲区B:null ——> echo "B<br />" // 输出进入缓冲区B ——> ob_start();// 新建缓冲区C:null ——> echo "C<br />" // 输出进入缓冲区C
——> ob_end_clean() // 缓冲区C被清空并关闭 ——> ob_end_flush() // 缓冲区B输出到上一级缓冲A,并关闭 ——> ob_end_clean() // 清空缓冲A并关闭 ——> 因此没有任何输出