在早期的 Web 開發中,伺服器端腳本產生的內容會立即逐行發送給瀏覽器。這不僅限制了在輸出前修改 HTTP 標頭(如設定 Cookie 或重導向)的靈活性,也錯失了對內容進行壓縮、快取等最佳化的機會。PHP 4 引入的輸出控制函數(Output Control Functions)徹底改變了這一局面,允許開發者將腳本輸出暫存於記憶體緩衝區,在適當時機再統一處理並發送。
ob_start():開啟輸出緩衝,後續所有輸出(echo、print、HTML 等)將導向內部緩衝區而非直接送往瀏覽器。ob_get_contents():取得目前緩衝區內的字串內容。ob_get_length():回傳緩衝區內容的位元組長度。ob_end_clean():清空緩衝區並關閉輸出緩衝,內容不會自動輸出。ob_implicit_flush(false):關閉隱含刷新,確保輸出僅在緩衝區滿或腳本結束時才發送。配合 Zlib 擴展,我們可以在腳本結束前對緩衝內容進行壓縮,大幅減少傳輸體積。以下是完整實作範例:
<?php
// 1. 啟動緩衝並關閉隱含刷新
ob_start();
ob_implicit_flush(0);
// 2. 產生頁面內容(可包含大量 HTML、echo、print 等)
print("Hey this is a compressed output!");
// 3. 取得緩衝內容並關閉緩衝
$contents = ob_get_contents();
ob_end_clean();
// 4. 偵測瀏覽器是否支援 gzip/deflate
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) {
// 發送正確的編碼標頭
header("Content-Encoding: gzip");
// Gzip 檔案標頭(ID1=0x1f, ID2=0x8b, CM=8=deflate, FLG=0, MTIME=0, XFL=0, OS=0)
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
// 計算原始資料大小與 CRC32
$size = strlen($contents);
$crc = crc32($contents);
// 壓縮資料(等級 9 最高)
$contents = gzcompress($contents, 9);
// gzcompress 回傳的資料結尾包含 4 位元組的 CRC 與 4 位元組的長度,
// 但標準 gzip 格式要求尾部為 CRC32 + ISIZE(原始長度 mod 2^32)。
// 這裡移除 gzcompress 產生的尾部 4 字節,改由手動附加標準 CRC 與 SIZE。
$contents = substr($contents, 0, -4);
// 輸出壓縮後的資料本體
echo $contents;
// 以 little-endian 依序輸出 CRC32 與原始長度(各 4 位元組)
function gzip_print_four_chars($val) {
for ($i = 0; $i < 4; $i++) {
echo chr($val % 256);
$val = floor($val / 256);
}
}
gzip_print_four_chars($crc);
gzip_print_four_chars($size);
} else {
// 不支援壓縮則直接輸出原始內容
echo $contents;
}
?>
除了壓縮,輸出緩衝還能輕鬆實現頁面級快取,減少資料庫查詢與運算開銷。基本邏輯如下:
md5($_SERVER['REQUEST_URI']))。is_valid() 判斷)。readfile() 輸出;否則啟動緩衝、產生內容、寫入快取檔後再輸出。<?php
$cache_file = '/cache/' . md5($_SERVER['REQUEST_URI']);
if (!file_exists($cache_file) || !is_valid($cache_file)) {
ob_start();
ob_implicit_flush(0);
// ... 這裡執行耗時的資料庫查詢、模板渲染等 ...
$content = ob_get_contents();
ob_end_clean();
file_put_contents($cache_file, $content);
}
readfile($cache_file);
?>
利用輸出緩衝捕獲動態生成的 XML 內容,再搭配 Sablotron 或 libxslt 擴展進行 XSLT 轉換,即可輕鬆支援多種輸出格式(HTML、WAP、PDF 等),實現「資料與呈現分離」的架構優勢。
PHP 的輸出控制函數提供了強大的介面,讓開發者能在輸出前對內容進行攔截、壓縮、快取或轉換。善用 ob_start() 搭配 gzcompress() 可顯著降低頻寬消耗並提升頁面載入速度;結合檔案快取機制則能大幅減輕伺服器負載。這些技巧在高流量、高效能要求的專案中極具實務價值。