2013-03-08 107 views
2

我试图找出为什么这个循环没有任何返回到浏览器:PHP无尽while循环混乱

while(1) { 
    echo "hello"; 
    flush(); 
    sleep(1); 
} 

我期待它返回“你好”到浏览器每一秒。 .. 我错了吗?现在这个页面似乎挂起了。

+0

你的HTTP服务器正在缓冲输出 – galchen 2013-03-08 20:36:32

+0

不是什么flush()的用途? – mootymoots 2013-03-08 20:38:28

+0

排序,阅读http://php.net/manual/en/function.flush.php – galchen 2013-03-08 20:40:05

回答

0

在收到整个页面之前,浏览器不会显示任何东西。 PHP不能完成你想要完成的任务。

在Javascript中,这很简单。

<script> 
    window.setInterval(function(){document.innerHTML += "<br> Hello"}, 1000) 
</script> 
+0

是的,它是有能力的,但不是为它构建的 – galchen 2013-03-08 20:37:20

+0

只有当没有什么东西在沿着其余的管道缓冲输出时,才有能力,并且浏览器和Web服务器在显示之前几乎总是缓冲输出。 – snostorm 2013-03-08 20:40:12

+0

更重要的是,在什么样的现实世界中,你甚至会想要这个功能? – snostorm 2013-03-08 20:41:44

3

PHP只在执行完成后输出。所以你所做的每一毫秒都会产生一个新的hello,并且由于你永远不会退出循环,所以你永远不会看到输出。

+0

是什么flush()是为了什么? – mootymoots 2013-03-08 20:38:07

+1

阅读刷新文档:http://php.net/manual/en/function.flush.php刷新“排序”的作品,但更多的时候,不是, – bizzehdee 2013-03-08 20:39:17

+0

不正确,你可以真正输出一行,但你有到'flush()'并且确保'output_buffering'被禁用,或者调用'ob_flush()'作为valentin所说的 – 2013-03-27 11:29:06

0

您应该认识到PHP是一种脚本语言,因为它仅在完成脚本后才返回输出。编辑:或者输出缓冲区填充后,谢谢@Marc B. 无论我会说这是更聪明的使用JS或如果你真的需要你的服务器,使用AJAX请求。

也许你应该考虑使用Javascript?这将允许你每秒添加内容(请记住JS在客户端运行,所以你可能不想让你的操作全部扩展)。

或者你可以考虑使用AJAX请求例如JQuery的,但可能是这个问题的范围...

+0

不完全正确。 PHP可以/会根据需要将输出发送给客户端。但只有当脚本完成和/或输出缓冲区填满时。很可能有一个php脚本发送无限数据,并且会很快显示在客户端。 – 2013-03-08 20:44:52

+0

你说得很对,谢谢我解决了我的答案,以反映这个评论:) – MrHug 2013-03-08 20:48:42

-1

添加到所有其他的答案,

要做到异步服务器推到客户端,您需要使用WebSockets。这是一个很大的课题,并没有完全标准化,但是确实有这样做的方法。如果您有兴趣搜索PHP Websockets。

0

也许是未为晚矣回答,但如果你想在这里刷新每一秒,我给你一个例子:

<?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'; 
2

要纠正我的答案,让你更好地理解,并为AJAX爱好者。 .. 你需要和额外的冲洗有..在 'ob_' 之一:

<?php 
while(1): 
    echo "hello"; 
    ob_flush(); flush(); 
    sleep(1); 
endwhile; 

这是大家谁需要知道的 '特技';)

+0

这不是一个好的答案,因为它不能可靠地工作(如果有的话),如文档[这里](http://stackoverflow.com/问题/ 5770917)和[ob_flush()的评论](http://www.php.net/manual/en/function.ob-flush.php#allnotes)。 AJAX是实现在所有浏览器中可靠且一致地提出问题的唯一方法。而无需修改服务器设置。 – mastaBlasta 2013-03-22 15:17:33

0

Valentin给了你正确的答案(upvote他/接受他的答案!),但没有解释为什么。这里的解释:

输出缓冲

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默认情况下启用。默认情况下,请参阅configuration variables将其关闭/打开。

0

好吧,卡洛斯批评我,因为我没有解释我的答案,但他的答案是含糊不清......用饼干,图层...... 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 

如果你不知道如何MA纽约层你有,你可以这样做:

while (@ob_end_clean()); 

和清洁每垃圾,你可以有,然后你的代码会工作得很好.. 完成snipp:

<?php 
while (@ob_end_clean()); 
while(1) { 
    echo "hello"; 
    flush(); 
    sleep(1); 
} 

氰..