PHP 輸出不直接送達瀏覽器,而是經過三層緩衝:PHP 緩衝 → Web Server 緩衝 → 瀏覽器緩衝。理解此機制,才能精準控制即時輸出、避免「Header already sent」錯誤,並優化傳輸效能。
output_buffering(預設 4096 bytes),ob_start() 手動開啟巢狀緩衝。mod_gzip、Nginx fastcgi_buffering、IIS responseBufferLimit。</table> 才顯示。| 函數 | 作用層級 | 說明 |
|---|---|---|
ob_flush() | PHP 緩衝 | 將 PHP 緩衝區內容推送到 Web Server |
flush() | Web Server 緩衝 | 要求 Web Server 將資料發送給瀏覽器 |
ob_end_flush() | PHP 緩衝 | 輸出並關閉最內層緩衝 |
ob_end_clean() | PHP 緩衝 | 丟棄並關閉最內層緩衝 |
ob_get_clean() | PHP 緩衝 | 取得內容並關閉緩衝(常用於模板引擎) |
<?php
// 1. 關閉 PHP 內建緩衝(若 php.ini 未關閉)
@ini_set('output_buffering', '0');
// 2. 開啟隱式緩衝以便控制
ob_implicit_flush(true);
echo str_pad('', 1024); // 滿足 IE/Edge 最小字元門檻
for ($i = 5; $i > 0; $i--) {
echo "步驟 $i 完成<br>";
ob_flush(); // 推送至 Web Server
flush(); // 推送至瀏覽器
sleep(1);
}
?>
輸出任何內容(含空白字元、BOM)前不得呼叫 header()、session_start()、setcookie()。解法:腳本最開頭處理 Header,或用 ob_start() 暫存輸出。
mod_gzip 或設定 SetOutputFilter DEFLATE 排除動態腳本。fastcgi_buffering off; 在 location 區塊。responseBufferLimit="0"。輸出 <br>、<div> 等區塊標籤,並墊足 1~2 KB 空白字元(str_pad('', 2048))。
<?php ob_start(); include 'template.php'; // 模板內 echo 內容 $html = ob_get_clean(); // 取得並清除緩衝 // 後續可對 $html 壓縮、替換、快取、回應 echo $html; ?>
掌握三層緩衝互動,能從容應對即時日誌、大檔下載、模板渲染等場景,寫出更可控的 PHP 應用。