PHP Conference Japan 2024

ob_end_clean

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

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

描述

ob_end_clean(): 布尔值

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

如果没有使用PHP_OUTPUT_HANDLER_REMOVABLE 标志启动的活动输出缓冲区,则ob_end_clean() 将失败。

即使ob_end_clean() 是在没有PHP_OUTPUT_HANDLER_CLEANABLE 标志的情况下启动的,它也会丢弃活动输出缓冲区的内容。

参数

此函数没有参数。

返回值

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

错误/异常

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

示例

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

示例 #1 ob_end_clean() 示例

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

参见

添加备注

用户贡献的笔记 11 条笔记

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(); 将引发错误。
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
"";
}
...
}
?>
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-Header 与脚本最后修改日期进行比较。

例如,您可以使用此技术动态生成图像。如果用户通过 If-Modified-Since-Header 指出他已经拥有图像版本,则无需生成它并让服务器最终将其丢弃,因为服务器只有在那时才会解释 If-Modified-Since-Header。
这节省了服务器负载并缩短了响应时间。
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');
?>
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 应用程序中的通用异常处理程序中使用它,在那里我清除缓冲区(但不清除包含调试信息的 header),并使用 readfile() 发送 500 错误页面。

PHP编程愉快!

塔马斯。
everling
18年前
请记住,mrfritz379 的示例(#49800)只是一个示例。您可以通过更有效的方式实现该示例的结果,而无需使用输出缓冲函数。

echo "<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_end_clean(),ob_gzhandler()也可能仍然将HTTP头“Content-Encoding”设置为“gzip”或“deflate”。这将在以下情况下导致问题:

1. 调用ob_gzhandler()。
2. 输出 "Some content"。
3. 调用ob_end_clean()。
4. 输出 "New content"。

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

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

1. 调用ob_gzhandler()。
2. 输出 "Some content"。
3. 调用ob_end_clean()。
4. 调用ob_gzhandler()。
5. 输出 "New content"。

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

一个解决方案是编写一个包装器,就像John Smith那样,为ob_gzhandler()编写一个包装器。
geoff at spacevs dot com
17年前
如果在使用“register_shutdown_function”注册的函数中调用ob_end_clean,那就太晚了,任何缓冲区都已经被发送到客户端。
Fusion Bay的Adam
18年前
您可能需要注意在回调函数中调用ob_end_clean()。我相信这可能会在PHP中产生无限循环。
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”相同。
mrfritz379
19年前
这可能已发布在其他地方,但我还没见过。
要在程序运行时运行进度指示器而无需输出输出缓冲区,可以使用以下方法:

echo "<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;

程序将继续打印“.”,而不打印文件列表。然后将打印“搜索完成”消息,然后是缓冲的文件列表。
To Top