用户级输出缓冲区可以从 PHP 代码中启动、操作和终止。每个缓冲区都包含一个输出缓冲区和一个关联的输出处理程序函数。
可以使用 ob_start() 函数或设置 output_buffering 和 output_handler php.ini 设置来打开输出缓冲。虽然两者都可以创建输出缓冲区,但 ob_start() 更灵活,因为它接受用户定义的函数作为输出处理程序,并且可以设置允许对缓冲区执行的操作(刷新、清除、删除)。使用 ob_start() 启动的缓冲区将从调用该函数的行开始生效,而使用 output_buffering 启动的缓冲区将从脚本的第一行开始缓冲输出。
PHP 还附带一个内置的 "URL-Rewriter"
输出处理程序,它启动自己的输出缓冲区,并且在任何时候只允许最多两个实例运行(一个用于用户级 URL 重写,另一个用于透明会话 ID 支持)。可以通过调用 output_add_rewrite_var() 函数和/或启用 session.use_trans_sid php.ini 设置来启动这些缓冲区。
捆绑的 zlib
扩展有自己的输出缓冲区,可以通过使用 zlib.output_compression php.ini 设置来启用。
注意:虽然
"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() 时,此标志无效。