萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 輸出緩衝控制函數詳解:ob_start、ob_get_contents、ob_end_clean、ob_flush

PHP Output Buffering 輸出緩衝區完整操作指南

輸出緩衝 (Output Buffering) 讓 PHP 腳本將輸出 (echo、print、HTML) 先存入記憶體緩衝區,而非直接發送給瀏覽器。可用於:捕獲輸出、壓縮、修改標頭、延遲輸出、模板引擎渲染等。

核心函數速查表

函數用途回傳值備註
ob_start(callable $callback=null, int $chunk_size=0, int $flags=PHP_OUTPUT_HANDLER_STDFLAGS)開啟輸出緩衝區bool可指定回調處理輸出 (如 ob_gzhandler 壓縮)
ob_get_contents()取得目前緩衝區內容**不清除**string|false常用於捕獲模板輸出、API 回應
ob_get_clean()取得內容**並清除/關閉**緩衝區string|false等同 ob_get_contents() + ob_end_clean()
ob_end_clean()**清除並關閉**緩衝區 (不輸出)bool丟棄內容
ob_end_flush()**輸出並關閉**緩衝區bool發送內容給瀏覽器
ob_flush()**送出**目前緩衝區內容 (不關閉)void需搭配 flush() 刷新 Web 伺服器/OS 緩衝
ob_clean()**清空**緩衝區內容 (不關閉)void保留緩衝區開啟狀態
flush()刷新 PHP/WEB 伺服器輸出緩衝到瀏覽器void通常 ob_flush(); flush(); 配合使用
ob_get_level()取得巢狀緩衝層級int0 表示無緩衝
ob_get_status()取得緩衝區狀態陣列array除錯用

常見使用模式

1. 捕獲輸出到變數 (模板引擎核心)

<?php
ob_start();
include 'template.php'; // 模板中 echo 輸出
$html = ob_get_clean(); // 取得內容並關閉緩衝
// 後續可對 $html 處理、快取、回傳 JSON 等
echo $html;
?>

2. 頁面壓縮輸出 (自動 gzip)

<?php
// 入口檔案最開頭
ob_start('ob_gzhandler'); // 自動判斷瀏覽器支援並壓縮
// ... 所有輸出會被壓縮
?>
  • 或在 php.ini 設定 zlib.output_compression = On。

3. 長時間執行腳本分批輸出 (進度條、串流)

<?php
ob_start();
for ($i = 1; $i <= 10; $i++) {
    echo "處理步驟 $i ...<br>\n";
    ob_flush(); // 送出 PHP 緩衝
    flush();    // 刷新 Web Server/OS 緩衝到瀏覽器
    sleep(1);   // 模擬耗時任務
}
ob_end_flush();
?>
  • 需關閉 Web 伺服器緩衝 (Nginx: proxy_buffering off;、Apache: SetOutputFilter DEFLATE 可能干擾)。
  • 某些瀏覽器需收到足夠內容 (如 256/1024 bytes) 才開始渲染。

4. 巢狀緩衝區管理

<?php
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 "Inner: $inner, Outer: $outer"; // Inner: B, Outer: AC
?>

完整流程範例:ob_start → 輸出 → 取得 → 清除 → 後處理 → 輸出

<?php
ob_start();
echo 'Hello ';
$out1 = ob_get_contents(); // 'Hello '
echo 'World';
$out2 = ob_get_contents(); // 'Hello World'
ob_end_clean(); // 清除並關閉,不輸出

var_dump($out1, $out2);
/*
string(6) "Hello "
string(11) "Hello World"
*/
?>

常見錯誤與注意事項

  • Headers already sent:若在 ob_start() 前已有輸出 (空白、BOM、echo),無法設定標頭。確保 ob_start() 在**最頂端** (
  • 遞迴/無限迴圈:回調函數中不可再次開啟緩衝或輸出。
  • 記憶體:大量輸出會佔用記憶體;分塊輸出用 ob_start(null, 4096) 設定 chunk size 自動 flush。
  • CLI 模式:預設無輸出緩衝,ob_start() 同樣有效。
  • PHP 8.1+:ob_start() 預設 flags 變更,PHP_OUTPUT_HANDLER_STDFLAGS 包含 CLEANABLE、REMOVABLE、FLUSHABLE。
copyright © 萬盛學電腦網 all rights reserved