2013-03-08 132 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); 
} 

氰..