echo/print_r → PHP output_buffering → Web Server Buffer (Apache/Nginx) → Browser Buffer → Browser Display
PHP 層面的緩衝由 output_buffering (php.ini) 控制,默認 Off 或 4096 字節。CLI 模式始終默認關閉。
解決 高速 CPU 生成內容 與 低速 I/O (網絡/磁盤) 傳輸 速度不匹配的問題。CPU 將數據寫入緩衝區即可繼續執行,緩衝區按策略(滿/腳本結束/手動刷新)輸出。
output_buffering 已開啟,相當於增加緩衝層級(棧結構);$callback:可選,輸出前處理函數(如 ob_gzhandler 壓縮、自定義替換);$chunk_size:緩衝區達到此大小自動刷新;$flags:PHP_OUTPUT_HANDLER_CLEANABLE 等控制標志。獲取當前活躍緩衝區內容,**不清除**,不關閉緩衝。常用於捕獲輸出後再決定是否發送。
| 函數 | 清除內容 | 關閉緩衝 | 返回值 |
|---|---|---|---|
| ob_clean() | 是 | 否 | bool |
| ob_end_clean() | 是 | 是 | bool |
陷阱:調用後之前的 echo 不會輸出。若需先輸出再清除,請先 ob_flush()。
ob_flush():將 PHP 內部緩衝區內容推送到 Web Server (SAPI) 層;flush():將 Web Server 緩衝區推送到客戶端(瀏覽器);ob_flush(); flush();。注意:mod_gzip、mod_deflate、Nginx fastcgi_buffering 等可能導致 flush() 不立即生效。
ob_get_clean() ≡ ob_get_contents() + ob_clean() ob_get_flush() ≡ ob_get_contents() + ob_flush()
輸出緩衝區內容並關閉緩衝,腳本結束時自動調用。
// 錯誤:想打印緩衝內容再清除 ob_start(); echo "Hello"; print_r(ob_get_contents()); // 打印 "Hello" 但這行本身也寫入緩衝! ob_clean(); // 清除所有,最終無輸出 // 正確: ob_start(); echo "Hello"; $data = ob_get_contents(); // 獲取 "Hello" ob_flush(); // 先刷出 "Hello" ob_clean(); // 再清除緩衝(現為空) echo "World"; // 繼續寫入新內容
ob_start(); // Level 1 echo "A"; ob_start(); // Level 2 echo "B"; ob_end_flush(); // 輸出 "B" 到 Level 1 緩衝 echo "C"; ob_end_flush(); // 輸出 "ABC" 到瀏覽器
內層 ob_end_flush() 將內容推送到外層緩衝,而非直接輸出。
ob_start(); include 'template.php'; $html = ob_get_clean();ob_implicit_flush(true); ob_end_flush(); 配合服務器配置;ob_start('ob_gzhandler'); 自動處理 Accept-Encoding;output_buffering 容錯;var_dump(ob_get_status(true)) 查看緩衝棧狀態。PHP 輸出緩衝是棧式結構,ob_start 入棧,ob_end_* 出棧。理解「PHP 緩衝 → SAPI 緩衝 → 瀏覽器緩衝」三層關係,正確使用 ob_flush() / flush() 配對,即可掌控輸出節奏,解決頭部已發送錯誤、實時輸出、模板捕獲等核心問題。