如何在php中实时获取输出结果?

9
如何实时获取 PHP 输出内容?而且不能将所有内容存储在内存或缓冲区中,也不能一次性地输出到浏览器中。如果我创建了一个名为 realtime-echo.php 的脚本,该如何做呢?
<?php
for($i = 0; $i < 10; $i++)
{
echo $i;
sleep(1);
}

当您从互联网浏览器访问它时,它会在9-10秒后给出以下输出。
0123456789

但是我希望输出的结果是,当我从浏览器访问PHP文件时,它应该给出0,然后等待1秒钟,在“0”之后添加“1”,再等待1秒钟,在“1”之后添加“2”,以此类推。我不知道这叫什么,像动画/实时更新。如何实现这一点?我正在开发一个项目,需要持续的输出,以便我可以密切关注发生了什么以及它的去向。谢谢。
3个回答

9

当你想要显示当前输出内容时,使用flush()函数。

一个快速的例子:

<?php
for ($i = 1; $i <= 10; $i++)
{
   echo '<p>' . $i . '</p>';
   flush();
   sleep(1);
}
?>

如果您正在使用输出缓冲,您还需要调用ob_flush()
注意:某些版本的Microsoft Internet Explorer只有在收到256个字节的输出后才开始显示页面,因此您可能需要在刷新之前发送额外的空白字符以使这些浏览器显示页面。
类似这样:
<?php
echo str_repeat(" ", 256); 
flush();
?>

不使用ob_start()函数的工作示例:

<?php
echo str_repeat(" ", 256);
for ($i = 1; $i <= 10; $i++)
{
    sleep(1);
    echo '<p>' . $i . '</p>';
    flush();
}
?>

好的,让我做其他修订。 - Paul Denisevich
还是一样的,我猜我漏了什么,我甚至添加了//关闭输出缓冲 ini_set('output_buffering', 'off'); //关闭PHP输出压缩 ini_set('zlib.output_compression', false); - user1642018
@AmbroseBwangatto,这段代码应该可以工作。但它也涉及到你的Web服务器。http://php.net/manual/en/function.flush.php - srain
这对我有效:<?php echo str_repeat(" ", 256); for ($i = 1; $i <= 10; $i++) { sleep(1); echo '<p>' . $i . '</p>'; flush(); } ?> - Paul Denisevich
请注意,HTTP协议有一定的封装方式,您的输出不会像封装允许的那样呈现为较小的步骤。 - Vengarioth
显示剩余2条评论

6

输出缓冲可能被打开并阻止实时输出。所以你需要使用 echo,结合 flush()ob_flush()

来源:http://php.net/manual/en/function.ob-flush.php#109314

header( 'Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
for( $i = 0 ; $i < 10 ; $i++ ){
    echo $i . '<br />';
    flush();
    ob_flush();
    sleep(1);
}
echo 'End ...<br />';

我尝试创建一个Fiddle代码示例,但是在Fiddle中不允许使用 sleep() 函数。因此,我创建了一个 GIF 动画。

输入图像描述


我使用 node.js 测试了您的示例,从 PHP 获取流并且看起来确实有效。但是,我的 Web 服务器配置为发送更大尺寸的块,因此流可能不总是立即明显。 - Adam Fowler
@AdamF 在我的服务器上的 php.ini 文件中,我将 output_buffering 指令设置为 output_buffering = 4096。你是如何解决你所描述的流媒体问题的? - Julian
@Julian,不知道这是否有帮助,但如果您需要在代码本地更改ini设置,可以添加以下行: ini_set('output_buffering', 512); - Jacopo Pace

5
PHP是一种解释型的服务器语言。使用PHP可以创建本地程序或实现Web应用程序的服务器端。如果您在命令行中运行PHP代码,则您的代码应该能按预期工作。然而,如果您通过浏览器使用PHP,则HTTP协议将适用请求-响应策略。如果您向浏览器发送请求,只有在执行脚本时才会收到服务器的响应。在服务器完成任务后,它将把响应发送回您的浏览器,您将一次性收到十个数字。这就是为什么您需要等待十秒钟,然后所有输出都会一次性显示出来的原因:因为服务器执行了休眠并收集了您的回显,然后将其发送回您的浏览器,而浏览器正在进行显示。
当然,如果您想在浏览器中显示十个服务器响应,则需要更好的方法。您可以使用轮询(使用Javascript的setIntervalsetTimeout函数在客户端等待几秒钟,并发送post请求到服务器,例如使用$.ajax) 。在服务器上处理请求并相应地响应。您的客户端应该具有回调函数,您可以在其中处理服务器的响应并相应地显示它。

这是否意味着flush()不是我要寻找的功能?如果可以解决问题,我也可以使用ajax。谢谢。 - user1642018
睡眠方法成功地在您的回声之间休眠。然而,问题在于PHP在执行完脚本后将答案发送回运行在用户计算机上的浏览器,因此您等待10秒钟而没有看到任何显示,然后响应到达并且一切立即显示。 - Lajos Arpad
1
@LajosArpad,我相信你在评论中谈到了 sleep() 函数,而AMB在他的评论中问到了 flush() 函数。我支持他的问题:Paul 使用 flush() 和 ob_flush() 方法对我有效。但是你的答案暗示它实际上不应该起作用。请澄清一下。 - texnic
1
@texnic,我解释了AMB所描述的行为原因。flush和ob_flush尝试将当前内容发送到客户端。 - Lajos Arpad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接