ob_end_clean

(PHP 4, PHP 5, PHP 7, PHP 8)

ob_end_clean清除(擦除)活动输出缓冲区的内容并将其关闭

描述

ob_end_clean(): bool

此函数调用输出处理程序(带有 PHP_OUTPUT_HANDLER_CLEANPHP_OUTPUT_HANDLER_FINAL 标志),丢弃其返回值,丢弃活动输出缓冲区的内容,并关闭活动输出缓冲区。

ob_end_clean() 将在没有使用 PHP_OUTPUT_HANDLER_REMOVABLE 标志启动的活动输出缓冲区的情况下失败。

ob_end_clean() 将丢弃活动输出缓冲区的内容,即使它是没有 PHP_OUTPUT_HANDLER_CLEANABLE 标志启动的。

参数

此函数没有参数。

返回值

成功时返回 true,失败时返回 false

错误/异常

如果函数失败,它将生成一个 E_NOTICE

示例

以下示例展示了一种简单的方法来清除活动输出缓冲区的内容

示例 #1 ob_end_clean() 示例

<?php
ob_start
();
echo
'不会显示的文本.';
ob_end_clean();
?>

参见

添加笔记

用户贡献笔记 12 个笔记

John Smith
20 年前
请注意,如果您使用回调启动了 ob_start 调用,即使您使用 ob_end_clean 丢弃了 OB,该回调仍将被调用。

因为一旦设置了回调,就无法从 OB 中删除它,所以阻止回调函数产生任何影响的唯一方法是执行以下操作:

<?php
$ignore_callback
= false;
ob_start('my_callback');
...
if(
$need_to_abort) {
$ignore_callback = true;
ob_end_clean();
...
}

function
my_callback(&$buffer) {
if(
$GLOBALS['ignore_callback']) {
return
"";
}
...
}
?>
Sam Yong - hellclanner at live dot com
13 年前
请注意,如果您在 ob_start 和 ob_end_clean 或 ob_end_flush 之间更改 zlib 输出压缩设置,您将收到错误:ob_end_flush() 无法删除 zlib 输出压缩缓冲区

示例

<?php

ob_start
();

$output = ob_get_contents();

ini_set('zlib.output_compression', '1');

ob_end_clean();

?>

ob_end_clean(); 在此示例中将引发错误。
baklanoid at gmail dot com
4 年前
如果您不确定输出缓冲区(是否启用),
您可以尝试以下保护措施

<?php

while (ob_get_level() !== 0) {
ob_end_clean();
}

// 或

while (ob_get_length() !== false) {
ob_end_clean();
}

?>
programmer at bardware dot de
21 年前
您可能希望阻止脚本执行,如果客户端已经拥有最新版本。
您可以像这样操作

ob_start();

$mtime=filemtime($_SERVER["SCRIPT_FILENAME"])-date("Z");
$gmt_mtime = date('D, d M Y H:i:s', $mtime) . ' GMT';

$headers = getallheaders();

if(isset($headers["If-Modified-Since"])) {
if ($headers["If-Modified-Since"] == $gmt_mtime) {
header("HTTP/1.1 304 Not Modified");
ob_end_clean();
exit;
}
}

$size=ob_get_length();
header("Last-Modified: ".$gmt_mtime);
header("Content-Length: $size");
ob_end_flush();

除了将 If-Modified-Since 标头与脚本最后修改日期进行比较之外,您当然也可以查询数据库或使用与脚本结果修改相关的任何其他日期。

例如,您可以使用此技术动态生成图像。如果用户通过 If-Modified-Since 标头表明他们已经拥有图像版本,则无需生成它,并让服务器最终丢弃它,因为服务器只有在此时才会解释 If-Modified-Since 标头。
这可以节省服务器负载并缩短响应时间。
netom at elte dot hu
14 年前
请注意,ob_end_clean() 会丢弃标头。

如果您想清除输出缓冲区,但不想清除标头(例如,因为您使用的是 firephp),那么解决方案如下

<?php
...

$headers = array();
if ( !
headers_sent() ) {
$headers = apache_response_headers();
}

ob_end_clean();
ob_start();

if ( !empty(
$headers ) ) {
foreach (
$headers as $name => $value ) {
header( "$name: $value" );
}
}

...
?>

我在 Web 应用程序中的通用异常处理程序中使用它,在那里我清除缓冲区(但不清除包含调试信息的标头),并使用 readfile() 发送 500 错误页面。

祝您 PHP 开发顺利!

Tamas.
daijoubuNOSP at Mvideotron dot com
20 年前
关于上一条评论
您也可以依赖 ETag,并简单地使用 time()

<?php
$time
= time();
$mins = 1;
if (isset(
$_SERVER['HTTP_IF_NONE_MATCH']) and str_replace('"', '', $_SERVER['HTTP_IF_NONE_MATCH'])+($mins*60) > $time)
{
header('HTTP/1.1 304 Not Modified');
exit();
}
else
{
header('ETag: "'.$time.'"');
}
echo
'Caching for ', $mins*60, 'secs<br/>', date('G:i:s');
?>
everling
17 年前
请记住,mrfritz379 的示例(#49800)只是一个示例。您可以通过更有效的方式实现该示例的结果,而无需使用输出缓冲函数

echo "<p>搜索正在运行。请耐心等待。。。</p>";
$output = "<p>文件列表:</p>\n";
if (is_dir($dir)) {
$dh = opendir($dir);

while (($fd = readdir($dh)) != false) {
echo " .";
$output .= $fd;
}
}
echo "</br>搜索完成!</p>\n";
echo $output;





除了 John Smith 的评论(#42939)之外,ob_gzhandler() 即使您调用 ob_end_clean(),也可能仍然将 HTTP 标头“Content-Encoding”设置为“gzip”或“deflate”。这将在以下情况下导致问题

1. 调用 ob_gzhandler()。
2. 回显“一些内容”;
3. 调用 ob_end_clean()。
4. 回显“新内容”;

在上述情况下,浏览器可能会收到“Content-Encoding: gzip”HTTP 标头,并尝试解压缩未压缩的“新内容”。浏览器将失败。

在以下情况下,此行为将不会被注意到

1. 调用 ob_gzhandler()。
2. 回显“一些内容”;
3. 调用 ob_end_clean()。
4. 调用 ob_gzhandler()。
5. 回显“新内容”;

这是因为第二个 ob_gzhandler() 将掩盖第一个 ob_gzhandler() 的缺失。

一个解决方案是编写一个包装器,就像 John Smith 所做的那样,用于 ob_gzhandler()。
geoff at spacevs dot com
17 年前
如果您在使用“register_shutdown_function”注册的函数中调用 ob_end_clean,那么为时已晚,任何缓冲区都将已发送到客户端。
Adam of Fusion Bay
18 年前
您可能需要小心地在回调函数中调用 ob_end_clean()。我相信这会导致 PHP 中出现无限循环。
mrfritz379
19 年前
这可能已发布在其他地方,但我没有看到。
要运行一个进度指示器,以便程序在运行时无需输出输出缓冲区,以下方法有效

echo "<p>搜索正在运行。请耐心等待。。。</p>";
$output = "<p>文件列表:</p>\n";
if (is_dir($dir)) {
$dh = opendir($dir);

while (($fd = readdir($dh)) != false) {
echo " .";
ob_start();
echo $fd;
$output .= ob_get_contents();
ob_end_clean();
}
}
echo "</br>搜索完成!</p>\n";
echo $output;

该程序将继续打印“.”,而不会打印文件列表。然后,将打印“搜索完成”消息,然后打印缓冲的文件列表。
tyler @
16 年前
关于 <geoff at spacevs dot com> 的说法,“如果您在使用“register_shutdown_function”注册的函数中调用 ob_end_clean,那么为时已晚,任何缓冲区都将已发送到客户端”,以下是我想出的解决方法。

<?php

function ClearBuffer($Buffer) {
return
"";
}

function
Shutdown() {
ob_start("ClearBuffer");
}

register_shutdown_function("Shutdown");

?>

这将清除所有进入输出缓冲区的内容。基本上,它与“STDOUT > /dev/null”相同。
Anonymous
6 年前
要安全地清除和关闭所有非致命输出缓冲区

<?php

function ob_end_clean_all() {
$handlers = ob_list_handlers();
while (
count($handlers) > 0 && $handlers[count($handlers) - 1] != 'ob_gzhandler' && $handlers[count($handlers) - 1] != 'zlib output compression') {
ob_end_clean();
$handlers = ob_list_handlers();
}
}
To Top