後來查了PHP手冊
http://tw.php.net/manual/en/book.outcontrol.php
在順序上,必須先用ob_flush再用flush
ob_flush();
flush();
ob_flush是把在PHP緩衝區(output_buffer)(假設有打開)的東西輸出,但並不是立刻輸出到螢幕上
flush則是把非PHP緩衝區,伺服器上準備輸出的資料輸出到瀏覽器上"顯示出來"
因此順序上必須先用ob_flush()把緩衝區上的資料輸出後,才能用flush()把從緩衝區輸出的資料給列印到螢幕上,不然光用ob_flush(),把緩衝區清空他並不會立刻把資料輸出到螢幕上
而只用flush(),資料全部在緩衝區他也沒東西可列印到螢幕上
網路上最常看到的例子
for($i=0;$i<10;$i++)
{
echo $i;
ob_flush();
flush();
sleep(1);
}
上面這隻程式會一秒輸出一個數字到螢幕上,可以試試把flush()或ob_flush()其中一個拿掉
就會變成十秒後全部輸出,而不是一次輸出一個字
上述狀況是在output_buffer打開的情況下,因為echo的東西會先把資料存到output_buffer
再從output_buffer頃印到螢幕上
上述程式碼結果其實等同於
ob_end_clean();//關閉output_buffer
for($i=0;$i<10;$i++)
{
echo $i;
flush();
sleep(1);
}
在output_buffer關閉的情況下,輸出資料不會搬到緩衝區,可以直接用flush()把他頃印出來
至於output_buffer打開的方式有兩種
第一種是修改php.ini的output_buffer選項
output_buffer = off
改成
output_buffer = N
N是一個數字,文件上建議是改成4096
第二種方法則是用他提供的ob_start()函數
- ob_start — Turn on output buffering
用法可以參照手冊,而要關閉output_buffer則是使用ob_end_clean 或ob_end_flush
- ob_end_clean — Clean (erase) the output buffer and turn off output buffering
- ob_end_flush — Flush (send) the output buffer and turn off output buffering
所以前面提到的例子完整一點,不修改php.ini的話應該是要
ob_start();//打開output_buffer
for($i=0;$i<10;$i++)
{
echo $i;
ob_flush();
flush();
sleep(1);
}
ob_end_clean();//關閉output_buffer
那就有個疑問,為何這麼麻煩要把資料先搬到緩衝呢
有個說法是可以提高效率
而官方另一種有說服力的理由,配合header修改
http://tw.php.net/manual/en/outcontrol.examples.basic.php
ob_start();
echo "Hello\n";
setcookie("cookiename", "cookiedata");
ob_end_flush();
上面這段程式,如果在output_buffer關閉的情況下使使用,會出現
Cannot modify header information - headers already sent
這段錯誤訊息
為什麼呢?看一下setcookie的說明
setcookie() defines a cookie to be sent along with the rest of the HTTP headers.
Like other headers,cookies must be sent before any output from your script (this is a protocol restriction).
This requires that you place calls to this function prior to any output,
including <html> and <head> tags as well as any whitespace.
上面的說明很清楚了,會動到header的部分,但是前幾篇文章有提到
header輸出之前不能有任何output到瀏覽器螢幕上,不然就會出現上面的error
http://hatsukiakio.blogspot.com/2009/07/cannot-send-session-cache-limiter.html
所以可以透過output_buffer先把輸出資料鎖在output_buffer裡面
這樣就可以執行header相關函數了
P.S output_buffer必須夠大,不然output_buffer滿了他一樣會輸出到螢幕上
這樣的話header函數依然會有危險
沒有留言:
張貼留言