使用者層輸出緩衝可以從 PHP 程式碼中啟動、操作和終止。每個緩衝區都包含一個輸出緩衝區和一個相關聯的輸出處理器函式。
可以使用 ob_start() 函式或設定 php.ini 中的 output_buffering 和 output_handler 設定來開啟輸出緩衝。雖然兩者都可以建立輸出緩衝區,但 ob_start() 更為彈性,因為它接受使用者自訂函式作為輸出處理程式,並且也可以設定允許在緩衝區上執行的操作(清空、清除、移除)。使用 ob_start() 啟動的緩衝區將從呼叫該函式的行開始生效,而使用 output_buffering 啟動的緩衝區將從腳本的第一行開始緩衝輸出。
PHP 也內建了一個 "URL-Rewriter"
輸出處理程式,它會啟動自己的輸出緩衝區,並且在任何時候最多只允許執行兩個實例(一個用於使用者層級的 URL 重寫,另一個用於透明的 Session ID 支援)。可以透過呼叫 output_add_rewrite_var() 函式和/或啟用 php.ini 中的 session.use_trans_sid 設定來啟動這些緩衝區。
內建的 zlib
擴充功能有自己的輸出緩衝區,可以透過 php.ini 中的 zlib.output_compression 設定來啟用。
注意:
"URL-Rewriter"
的特殊之處在於它在任何時候最多只允許執行兩個實例,而所有使用者層級的輸出緩衝區都使用與 ob_start() 相同的底層緩衝區,其功能由自訂輸出處理函式實現。因此,它們的所有功能都可以透過使用者程式碼來模擬。
清空會傳送並捨棄作用中緩衝區的內容。當輸出的大小超過緩衝區的大小時,腳本結束時,或呼叫 ob_flush()、ob_end_flush() 或 ob_get_flush() 時,輸出緩衝區就會被清空。
呼叫 ob_end_flush() 或 ob_get_flush() 將會關閉作用中的緩衝區。
清空緩衝區會清空輸出處理程式的回傳值,該值可能與緩衝區的內容不同。例如,使用 ob_gzhandler() 將會壓縮輸出並清空已壓縮的輸出。
可以透過呼叫 ob_get_contents()、ob_get_clean() 或 ob_get_flush() 來取得作用中緩衝區的內容。
如果只需要緩衝區內容的長度,ob_get_length() 或 ob_get_status() 將會以位元組為單位傳回內容的長度。
呼叫 ob_get_clean() 或 ob_get_flush() 將會在傳回其內容後關閉作用中的緩衝區。
可以透過呼叫 ob_clean()、ob_end_clean() 或 ob_get_clean() 來清除作用中緩衝區的內容。
呼叫 ob_end_clean() 或 ob_get_clean() 將會關閉作用中的緩衝區。
輸出緩衝區可以透過呼叫 ob_end_clean()、ob_end_flush()、ob_get_flush() 或 ob_get_clean() 來關閉。
沒有使用 PHP_OUTPUT_HANDLER_REMOVABLE
旗標啟動的輸出緩衝區無法關閉,並且可能會產生 E_NOTICE
錯誤訊息。
在腳本結束或呼叫 exit() 時,所有尚未關閉的輸出緩衝區將會由 PHP 的關閉程序清空並關閉。緩衝區將會以它們啟動的相反順序清空和關閉。最後啟動的緩衝區會最先被清空,而最先啟動的緩衝區會最後被清空和關閉。
如果不希望清空緩衝區的內容,則應使用自訂輸出處理程序來防止在關閉程序中清空。
如果在輸出處理程序中拋出未捕捉的例外,程式將會終止,並且關閉程序會呼叫該處理程序,之後會清空「未捕捉的例外 (Uncaught Exception)」錯誤訊息。
如果未捕捉的例外是在由 ob_flush()、ob_end_flush() 或 ob_get_flush() 呼叫的處理程序中拋出,則緩衝區的內容會在錯誤訊息之前被清空。
如果在關閉程序期間,輸出處理程序中拋出未捕捉的例外,則該處理程序將會終止,並且緩衝區的內容和錯誤訊息都不會被清空。
注意:如果處理程序拋出例外,則會設定其
PHP_OUTPUT_HANDLER_DISABLED
狀態旗標。
如果在輸出處理程序中引發非致命錯誤,程式將會繼續執行。
如果非致命錯誤是在由 ob_flush()、ob_end_flush() 或 ob_get_flush() 呼叫的處理程序中引發,則緩衝區會根據處理程序的傳回值清空某些資料。如果處理程序傳回 false
,則緩衝區和錯誤訊息都會被清空。如果傳回任何其他值,則會清空處理程序的傳回值,但不會清空錯誤訊息。
注意:如果處理程序傳回
false
,則會設定其PHP_OUTPUT_HANDLER_DISABLED
狀態旗標。
如果在輸出處理程序中引發致命錯誤,程式將會終止,並且關閉程序會呼叫該處理程序,之後會清空錯誤訊息。
如果在 ob_flush()、ob_end_flush() 或 ob_get_flush() 呼叫的處理程式中發生致命錯誤,則緩衝區的內容會在錯誤訊息之前被清空。
如果在關閉期間的輸出處理程式中發生致命錯誤,程式會在不清空緩衝區或顯示錯誤訊息的情況下終止。
在特定情況下,處理程式中產生的輸出會與緩衝區的內容一起被清空。此輸出不會附加到緩衝區,也不是 ob_get_flush() 返回的字串的一部分。
在清空操作期間(呼叫 ob_flush()、ob_end_flush()、ob_get_flush() 以及關閉期間),如果處理程式的返回值是 false
,則緩衝區的內容會先被清空,然後再輸出。如果在關閉期間未呼叫處理程式,則處理程式拋出異常或呼叫 exit() 會導致相同的行為。
注意:如果處理程序傳回
false
,則會設定其PHP_OUTPUT_HANDLER_DISABLED
狀態旗標。
每次呼叫輸出處理程式時,緩衝區 flags
位元遮罩的 處理程式狀態旗標 都會被設定,並且是 ob_get_status() 返回的 flags
的一部分。如果處理程式成功執行且未返回 false
,則會設定 PHP_OUTPUT_HANDLER_STARTED
和 PHP_OUTPUT_HANDLER_PROCESSED
。如果處理程式返回 false
或在執行時拋出異常,則會設定 PHP_OUTPUT_HANDLER_STARTED
和 PHP_OUTPUT_HANDLER_DISABLED
。
注意: 如果設定了處理程式的
PHP_OUTPUT_HANDLER_DISABLED
,則呼叫 ob_end_clean()、ob_end_flush()、ob_get_clean()、ob_get_flush()、ob_clean()、ob_flush() 或在 PHP 關閉程序期間,將不會呼叫該處理程式。在 PHP 8.4.0 之前,呼叫 ob_clean() 或 ob_flush() 時,此旗標無效。