預設 PHP 腳本輸出 (`echo`、`print`、HTML 區塊) 直接送往瀏覽器。開啟輸出緩衝後,輸出資料暫存於記憶體緩衝區,**不立即發送**,直到腳本結束或手動 `flush()`/`ob_end_flush()`。這解決了「輸出後無法送出 Header」的經典問題。
| 函式 | 說明 |
|---|---|
| `ob_start([callback])` | 開啟緩衝,可選回呼函式處理緩衝內容 (如 `ob_gzhandler` 壓縮) |
| `ob_get_contents()` | 取得目前緩衝區字串內容 |
| `ob_get_length()` | 取得緩衝區長度 (位元組) |
| `ob_end_flush()` | 輸出緩衝內容並關閉緩衝 |
| `ob_end_clean()` | 捨棄緩衝內容並關閉緩衝 |
| `ob_clean()` | 清空緩衝區但保持開啟 |
| `ob_flush()` | 輸出緩衝內容但保持開啟 |
| `flush()` | 系統層級刷新 (Web Server → 瀏覽器),需配合 `ob_flush()` |
| `ob_implicit_flush([flag])` | 開啟/關閉絕對刷新 (每輸出即送出) |
<?php
ob_start();
echo "Hello "; // 不會立即輸出
header("Location: index.php"); // 正常運作,未觸發 "Headers already sent"
ob_end_flush();
<?php
ob_start();
include 'template.php'; // 模板輸出到緩衝區
$content = ob_get_contents(); // 取得渲染後字串
ob_end_clean();
// 後處理:關鍵字替換、壓縮、快取
$content = str_replace('{SITE_NAME}', 'MySite', $content);
file_put_contents('cache/page.html', $content);
echo $content;
ob_start();
// 複雜邏輯、資料庫查詢、視圖渲染
$this->load->view('page', $data);
$html = ob_get_contents();
ob_end_clean();
$fp = fopen('public/page.html', 'w');
fwrite($fp, $html);
fclose($fp);
ob_start();
phpinfo();
$info = ob_get_contents();
ob_end_clean();
file_put_contents('phpinfo.html', $info);
ob_start('ob_gzhandler'); // 自動偵測瀏覽器支援並壓縮
// 或手動
ob_start();
echo $content;
$gz = gzencode(ob_get_contents(), 9);
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($gz));
echo $gz;
<?php
ob_implicit_flush(true); // 等同 ob_implicit_flush(1)
header('Content-Type: text/plain');
for ($i = 1; $i <= 10; $i++) {
echo "Processing step $i...\n";
sleep(1); // 模擬耗時操作
}
// 瀏覽器會逐行顯示,不等全部結束
可多次呼叫 `ob_start()`,形成堆疊。`ob_end_flush()`/`ob_end_clean()` 僅操作**最內層**緩衝區。
ob_start(); // Level 1
echo "A";
ob_start(); // Level 2
echo "B";
$inner = ob_get_clean(); // 取得 "B",關閉 Level 2
echo "C";
$outer = ob_get_clean(); // 取得 "AC",關閉 Level 1
echo $outer . $inner; // ACB
| 錯誤 | 原因 | 解決 |
|---|---|---|
| Headers already sent | `ob_start()` 前已有輸出 (空白、BOM、include 檔案輸出) | 確保 `ob_start()` 在檔案最頂端、` |
| 輸出亂序/重複 | 巢狀緩衝未正確配對 `ob_end_*` | 使用 `ob_get_level()` 除錯,確保開啟/關閉配對 |
| Session 失效 | `session_start()` 在 `ob_start()` 之後但輸出前 | `session_start()` 應在最頂端,或依賴 `session.auto_start` |