PHP Conference Japan 2024

ob_implicit_flush

(PHP 4, PHP 5, PHP 7, PHP 8)

ob_implicit_flush開啟/關閉隱式清空

說明

ob_implicit_flush(布林值 $enable = true):

ob_implicit_flush() 會開啟或關閉隱式清空。啟用隱式清空後,每當程式碼區塊產生輸出時,都會執行一次清空操作,因此不再需要明確呼叫 flush()

注意 輸出空字串或傳送標頭不被視為輸出,不會導致清空操作。

注意 此函式對使用者層級的輸出處理程式沒有任何作用,例如由 ob_start()output_add_rewrite_var() 啟動的處理程式。

參數

enable

true 表示開啟隱式清空,false 則表示關閉。

傳回值

無傳回值。

更新日誌

版本 說明
8.0.0 enable 參數現在需要 bool 值;先前需要 int 值。

參見

  • flush() - 清空系統輸出緩衝區
  • ob_start() - 開啟輸出緩衝
  • ob_end_flush() - 清空(傳送)目前輸出處理程式的傳回值,並關閉目前輸出緩衝區

新增註釋

使用者貢獻的註釋 6 則註釋

29
Pedro Gimeno
9 年前
請注意,ob_implicit_flush 這個名稱具有誤導性。儘管名稱如此,但此函式並*不*適用於使用者輸出緩衝區,也就是其他 ob_* 函式所使用的緩衝區。它*不會*自動執行 ob_flush(),而是自動執行 flush()。這是不同的。

例如,以下程式碼:

<?php
ob_implicit_flush
();
for(
$i = 0; $i < 10; $i++)
{
echo
"$i\n";
sleep(1);
}
?>

等同於以下程式碼:

<?php
for ($i = 0; $i < 10; $i++)
{
echo
"$i\n";
flush();
sleep(1);
}
?>

如果在 php.ini 中將 'output_buffering' 設定為 'on',則該程式碼直到結束才會輸出任何內容。遺憾的是,據我所知,沒有辦法在每次輸出後隱式執行 ob_flush()。

如果您希望輸出內容即時產生,一個解決方案是在程式碼的開頭 *同時* 加入 ob_end_clean() 或 ob_end_flush()

<?php
ob_end_flush
();
ob_implicit_flush();
for (
$i = 0; $i < 10; $i++)
{
echo
"$i\n";
sleep(1);
}
?>

這樣就會邊執行邊輸出。如果您只想讓部分輸出即時顯示,而其餘部分則需要緩衝,那麼這就會產生問題。在這種情況下,由於沒有函式可以在每次執行時隱式呼叫 ob_flush(),您需要明確地呼叫它。例如,以下程式碼可以運作:

<?php
ob_start
(); // 如果 php.ini 中的 output_buffering 已開啟,則不需要此行
ob_implicit_flush(); // 在每次 ob_flush() 之後隱式呼叫 flush()

echo "這段輸出會被緩衝。\n";
echo
"這段也是。\n";

for (
$i = 0; $i < 10; $i++)
{
echo
"$i\n";
ob_flush();
sleep(1);
}
?>

另請注意,某些瀏覽器可能會等到它們收到一定量的輸出才會顯示。詳情請參閱 flush [ https://php.dev.org.tw/manual/en/function.flush.php ]。我使用 Firefox (Iceweasel 17.0) 時就遇到這種情況;除非一開始就輸出 1024 位元組,否則它不會開始輸出。
3
damian at thebestisp dot dot dot com
8 年前
有些人似乎使用這個方法來解決輸出緩衝的問題,而不是簡單地將其關閉。對我來說,如果您使用了輸出緩衝,那肯定是有原因的,否則您會直接執行程式碼並使用 ob_flush() 或 ob_end_flush(),執行程式碼,然後可能再次使用 ob_start()。
以下是如何正確結束所有輸出緩衝區,而無需抑制錯誤(因為沒有任何緩衝區)。如果您確實需要單層輸出緩衝,我也包含了相關程式碼。
<?php
#完全清除輸出緩衝區
while (ob_get_level()) {ob_end_flush();}

#如果不是 CLI 環境,請確保我們有 1 層輸出緩衝。
$notcli=(int)(PHP_SAPI!=='cli');
while ((
$diff=ob_get_level()-$notcli)!==0) {
if (
$diff>0) {ob_end_flush();}
else {
ob_start();}
}
7
rocca at start dot ca
17 年前
您也可以在 Linux/Apache 環境下取得未緩衝的輸出,而不必在每一行後呼叫隱式清空函式:

ob_implicit_flush(true);
ob_end_flush();

... 將以上程式碼放在腳本的開頭。
6
Paul Yanchenko
18 年前
在控制台中使用 ob_implicit_flush() 還有另一種解決方法。雖然它的運作方式不如預期,但您可以在 ob_start() 中指定 chunk_size=2 來獲得類似的結果。

<?php
ob_start
('ob_logstdout', 2);
?>

這樣會導致每個新行(以 \n 結尾)都會清空輸出緩衝區。

希望這對您有所幫助。
5
calimero at Creatixnet dot com
21 年前
######### 注意 ##########

ob_implicit_flush 有一個錯誤(或至少是一個非預期的特性),這個問題已在 PHP bugtracker 上討論過。

http://bugs.php.net/bug.php?id=23877
http://bugs.php.net/bug.php?id=16676

像這樣的程式碼將無法正常運作:

<?
// 這在 Linux 上不會如預期般運作。
ob_implicit_flush (1);
for($i=0;$i<10;$i++) {
echo "grrrrrrrrrr\n";
sleep(1);
}
?>

這個問題發生在 Linux 版本的 PHP 中,在 4.3.3 之前的 php4 所有版本中都會出現(後續版本未知),php5 beta1 中也存在。ob_implicit_flush 對命令列(控制台、CLI)腳本沒有作用,完全不會進行任何清空,所有輸出將在腳本結束時發送。

有一個使用 ob_end_flush() 和 ob_flush 的解決方法,如下所示:

<?
// 這個方法有效!
ob_end_flush();
for($i=0;$i<10;$i++) {
echo "yeah :-))))\n";
@ob_flush();
sleep(1);
}
?>

希望這能有所幫助。這本來可以幫助我的...
2
mhumphrey at _spammenot_designvision dot com
21 年前
根據實驗,使用 session.use_trans_sid=1 的 session 設定似乎會強制緩衝輸出,無論這個設定為何。

我的猜測是,這是因為 PHP 需要在輸出中搜尋 URL,以便自動添加 Session ID。它必須等到腳本輸出完成後才能開始替換,而不是「即時」執行。

當我註釋掉 session_start() 行時,瀏覽器會持續收到輸出。將其放回後,只有在頁面完全載入後才會看到內容。將 session.use_trans_sid 更改為 0 後,我又會持續收到輸出。
To Top