我试图弄清楚为什么这个循环不会向浏览器返回任何内容:
while(1) {
echo "hello";
flush();
sleep(1);
}
我期待它每秒向浏览器返回“你好”......我错了吗?现在页面似乎只是挂起。
我试图弄清楚为什么这个循环不会向浏览器返回任何内容:
while(1) {
echo "hello";
flush();
sleep(1);
}
我期待它每秒向浏览器返回“你好”......我错了吗?现在页面似乎只是挂起。
PHP 仅在执行完成后输出。所以你所做的就是每毫秒生成一个新的 hello,并且由于你从不退出循环,所以你永远看不到输出。
为了更正我的答案并让您更好地理解,并且对于 AJAX 爱好者......你需要在那里额外冲洗......'ob_'一个:
<?php
while( 1 ):
echo "hello";
ob_flush( ); flush();
sleep( 1 );
endwhile;
这是每个需要知道的人的“诀窍”;)
Valentin给了你正确的答案(支持他/接受他的答案!),但没有解释原因。这是解释:
PHP 不会立即输出到浏览器,它会等待有一些内容发送到浏览器(可能以 1024、2048 或 4096 字节的块发送),或者在执行结束时。调用flush()
使 PHP 发送数据,但不止一层缓冲。一种是内部缓冲(我刚刚评论过),但您可以添加更多缓冲层。假设这段代码:
<?php
echo "hi";
setcookie('mycookie', 'somevalue');
?>
该setcookie()
函数向浏览器发送一个 http 标头,但它不能这样做,因为在 HTTP 中,服务器(或客户端,两种方式都相同)必须首先发送所有标头,一个空行,然后是内容。如您所见,您在标头之前输出了一些内容(hi),因此它失败了(因为内部缓冲遵循相同的执行顺序)。
您可以使用 php 函数添加另一层输出缓冲ob_*()
。通过ob
缓冲它只缓冲内容输出,而不是 HTTP 标头。您可以使用它们来获取直接输出到浏览器的函数的输出,例如var_dump()
. 此外,您可以嵌套以下层ob
:
<?php
// start first level of output buffering
ob_start();
echo "nesting at level ", ob_get_level(), "<br />\n"; // prints level 1
echo "hi<br />";
ob_start();
echo "nesting at level ", ob_get_level(), "<br />\n"; // prints level 2
var_dump($_POST);
$post_dump = ob_get_clean();
// this will print level 1, because ob_get_clean has finished one level.
echo "nesting at level ", ob_get_level(), "<br />\n";
echo "The output of var_dump(\$_POST) is $post_dump<br />\n";
// in spite of being inside a layer of output_buffering, this will work
setcookie('mycookie', 'somevalue');
// flush the current buffer and delete it (will be done automatically at the
// end of the script if not called explicitly)
ob_end_flush();
可能您的 PHP 服务器默认启用了 output_buffering。查看配置变量以默认关闭/打开它。
好的,卡洛斯批评我,因为我没有解释我的答案,但他的答案是含糊的......用饼干,层...... POST,ob_levels......:OO到很多关于真正问题没有真正意义的信息用户,但我会告诉你为什么你的代码不起作用。因为您在 php.ini 中设置了输出缓冲,例如:
output_buffering = On
或者
output_buffering = 4096 (default setting on most distributions)
这就是为什么你需要额外的'ob_flush()'来摆脱任何垃圾输出..
所以...要使您的代码正常工作,您有两个选择:
1). set output_buffering = 0 or Off (if you have access to the php.ini)
2). ob_flush many times as layers of buffering you have
如果您不知道您有多少层,您可以执行以下操作:
while (@ob_end_clean( ));
并清理你可能拥有的所有垃圾,然后你的代码就可以正常工作了。完整的片段:
<?php
while (@ob_end_clean( ));
while(1) {
echo "hello";
flush();
sleep(1);
}
赛亚..
在收到整个页面之前,浏览器不会显示任何内容。PHP 无法完成您想要完成的工作。
在 Javascript 中,这非常简单。
<script>
window.setInterval(function(){document.innerHTML += "<br> Hello"}, 1000)
</script>
您应该意识到 PHP 是一种脚本语言,因为它仅在完成脚本后才返回输出。编辑:或者在输出缓冲区被填满后,感谢@Marc B。不管我会说为此使用 JS 或者如果你真的需要你的服务器更明智,请使用 AJAX 请求。
也许您应该考虑使用 Javascript?这将允许您每秒添加内容(请记住,JS 在客户端运行,因此您可能不想让您的操作变得如此广泛。)
或者,您可以考虑通过例如 JQuery 使用 AJAX 请求,但这可能超出了这个问题的范围......
也许回答还不算晚,但是如果您想在这里每秒刷新一次,我给您一个示例:
<?php
echo "Flushing every second ...\n";
flush( );
$seconds = array (0,1,2,3,4,5,6,7,8,9);
foreach ($seconds as $second):
echo $second . "\n";
sleep( 1 );
@ob_flush( ); flush( );
endforeach;
echo 'I flashed 10 second :P';
添加到所有其他答案,
要对客户端进行异步服务器推送,您需要使用 WebSockets。这是一个庞大的主题,并没有完全标准化,但肯定有办法做到这一点。如果您有兴趣搜索 PHP Websockets。