PHP 輸出緩沖是理解「為什麼 header() 可以在 echo 之後調用」、「如何實現漸進式輸出」的關鍵。本文深度解析三級緩沖架構、核心函數差異、瀏覽器兼容性陷阱與調試技巧。
PHP 腳本 → PHP Buffer (output_buffering) → Web Server Buffer (Apache/Nginx) → Browser Buffer → 用戶可見
output_buffering = 4096),可在 php.ini 配置| 函數 | 作用層級 | 說明 |
|---|---|---|
ob_start() | PHP | 開啟輸出緩沖,可指定回調處理輸出 |
ob_flush() | PHP | 刷新 PHP 緩沖區到 Web Server |
flush() | Web Server | 刷新 Web Server 緩沖區到瀏覽器 |
ob_end_flush() | PHP | 輸出緩沖內容並關閉緩沖 |
ob_end_clean() | PHP | 丟棄緩沖內容並關閉緩沖 |
ob_get_contents() | PHP | 獲取緩沖內容不輸出 |
ob_get_clean() | PHP | 獲取並清空緩沖 |
<?php
echo "南無阿彌陀佛<br>";
header("Content-Type: text/html; charset='utf-8'");
echo "真善忍好!";
// 正常輸出,因為 PHP Buffer 尚未刷新到 Web Server
?>
但若手動刷新:
<?php
echo "南無阿彌陀佛<br>";
ob_flush(); // 強制刷新 PHP Buffer
header("Content-Type: text/html; charset='utf-8'"); // 錯誤:headers already sent
echo "真善忍好!";
?>
<?php
// 關鍵:填滿瀏覽器緩沖區門檻
echo str_pad('', 4096) . "\n"; // 或 256 字節針對 IE
for ($i = 10; $i > 0; $i--) {
echo $i . "<br>";
ob_flush(); // PHP 層
flush(); // Web Server 層
sleep(1);
}
?>
完整模板:
<?php
// 1. 禁用壓縮(否則 Web Server 會緩存壓縮後再發送)
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('output_buffering', 'Off');
// 2. 發送足夠填充
echo str_repeat(' ', 4096);
// 3. 循環輸出 + 雙重刷新
foreach ($data as $item) {
echo $item . "<br>";
ob_flush();
flush();
usleep(100000); // 微秒延遲
}
?>
fastcgi_buffering off;str_pad 填充ob_start() 會疊加,注意嵌套調用ob_get_clean())輸出緩沖看似簡單,實則涉及多層協作。掌握其原理,能解決許多「不可思議」的輸出異常問題。