PHP Conference Japan 2024

ob_implicit_flush

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

ob_implicit_flush启用/禁用隐式刷新

描述

ob_implicit_flush(bool $enable = true): void

ob_implicit_flush() 将启用或禁用隐式刷新。隐式刷新会在每一段产生输出的代码块之后执行刷新操作,因此不再需要显式调用 flush()

注意: 打印空字符串或发送报头不被视为输出,不会导致刷新操作。

注意: 此函数对用户级别的输出处理器(例如由 ob_start()output_add_rewrite_var() 启动的处理器)没有任何影响。

参数

enable

true 用于启用隐式刷新,false 用于禁用。

返回值

不返回任何值。

变更日志

版本 描述
8.0.0 enable 现在期望一个 bool 值;以前期望一个 int 值。

参见

  • flush() - 刷新系统输出缓冲区
  • ob_start() - 启用输出缓冲
  • ob_end_flush() - 刷新(发送)活动输出处理器的返回值并关闭活动输出缓冲区

添加注释

用户贡献的注释 6 条注释

Pedro Gimeno
9 年前
请注意,ob_implicit_flush 的名称具有误导性。尽管其名称如此,但此函数不适用于用户输出缓冲区,即其他 ob_* 函数使用的缓冲区。它不会执行自动 ob_flush()。它会执行自动 flush()。两者是不同的。

例如,以下脚本

<?php
ob_implicit_flush
();
for(
$i = 0; $i < 10; $i++)
{
echo
"$i\n";
sleep(1);
}
?>

将等效于以下脚本

<?php
for ($i = 0; $i < 10; $i++)
{
echo
"$i\n";
flush();
sleep(1);
}
?>

如果在 php.ini 中将 'output_buffering' 设置为 'on',则该脚本直到结束才会输出任何内容。不幸的是,据我所知,没有办法在每次输出后执行隐式 ob_flush()。

如果希望输出在生成时立即显示,一种解决方案是在脚本开头添加 *ob_end_clean()* 或 *ob_end_flush()*

<?php
ob_end_flush
();
ob_implicit_flush();
for (
$i = 0; $i < 10; $i++)
{
echo
"$i\n";
sleep(1);
}
?>

这将按顺序输出。只有当您只想让一部分输出实时显示,而其余部分缓冲时,这才是问题。在这种情况下,由于没有函数可以每次都执行隐式 ob_flush(),因此您需要显式调用它。例如,这有效

<?php
ob_start
(); // 如果 php.ini 中 output_buffering 为 on,则不需要
ob_implicit_flush(); // 在每次 ob_flush() 后隐式调用 flush()

echo "This output is buffered.\n";
echo
"As is this.\n";

for (
$i = 0; $i < 10; $i++)
{
echo
"$i\n";
ob_flush();
sleep(1);
}
?>

另请注意,某些浏览器可能会等到它们获得一定数量的输出。有关详细信息,请参阅 flush [ https://php.net/manual/en/function.flush.php ]。在我的 Firefox (Iceweasel 17.0) 案例中就是这样;除非我在开始时输出 1024 字节,否则它不会开始输出。
damian at thebestisp dot dot dot com
8 年前
似乎有些人正在使用它来解决输出缓冲问题,而不是简单地将其关闭。在我看来,如果您有输出缓冲区,则它是有原因的,否则您要么执行一些操作并使用 ob_flush() 或 ob_end_flush(),执行一些操作,然后可能再次使用 ob_start()。
以下是如何正确结束所有输出缓冲区,而无需抑制错误(因为没有任何缓冲区)。如果您想要单层输出缓冲,我也包含了一段代码。
<?php
# 完全清除输出缓冲区
while (ob_get_level()) {ob_end_flush();}

# 如果这不是 CLI,请确保我们有一层输出缓冲区。
$notcli=(int)(PHP_SAPI!=='cli');
while ((
$diff=ob_get_level()-$notcli)!==0) {
if (
$diff>0) {ob_end_flush();}
else {
ob_start();}
}
rocca at start dot ca
17 年前
您还可以使用 Linux/Apache 获取无缓冲输出,而无需在每一行之后执行隐式刷新,方法是在脚本开头调用

ob_implicit_flush(true);
ob_end_flush();

Paul Yanchenko
18 年前
在控制台中还有另一种 ob_implicit_flush() 的解决方法。是的,它不能按预期工作,但是您可以通过在 ob_start() 中指定 chunk_size=2 来获得类似的结果

<?php
ob_start
('ob_logstdout', 2);
?>

这将导致每一行(以 \n 结尾)都刷新输出缓冲区。

希望这能帮到您。
calimero at Creatixnet dot com
21 年前
######### 注意 ##########

ob_implicit_flush 存在一个错误(或至少是一个意外的功能),已经在 PHP 错误跟踪器中讨论过

http://bugs.php.net/bug.php?id=23877
http://bugs.php.net/bug.php?id=16676

这样的代码将不起作用

<?
// 这在 Linux 上不会按预期工作。
ob_implicit_flush (1);
for($i=0;$i<10;$i++) {
echo "grrrrrrrrrr\n";
sleep(1);
}
?>

此特性出现在 Linux 版本的 PHP 中,在 php4 4.3.3 之前的所有版本中都存在(后续版本尚不清楚),也在 php5 beta1 中存在。`ob_implicit_flush` 对命令行(控制台,CLI)脚本**无效**,不会进行任何刷新操作,所有输出将在脚本结束时发送。

可以使用 `ob_end_flush()` 和 `ob_flush` 作为变通方法,如下所示:

<?
// 这有效!
ob_end_flush();
for($i=0;$i<10;$i++) {
echo "yeah :-))))\n";
@ob_flush();
sleep(1);
}
?>

希望这能有所帮助。它本来可以帮到我的……
mhumphrey at _spammenot_designvision dot com
21 年前
通过实验,看起来使用会话且 `session.use_trans_sid=1` 将强制缓冲输出,而不管此设置如何。

我猜测这是为了让 PHP 能够在输出中查找 URL,以便自动向其添加会话 ID。它必须等到脚本输出完成之后才能开始替换,而不是“动态”地进行。

当我注释掉我的 `session_start()` 行时,我会持续向浏览器输出内容。把它放回去,只有在页面完全加载后才能看到页面。将 `session.use_trans_sid` 改为 0,我又可以持续输出内容了。
To Top