如何在发生时从 php 获取实时输出?

Posted

技术标签:

【中文标题】如何在发生时从 php 获取实时输出?【英文标题】:How to get realtime output from php as it happens? 【发布时间】:2013-10-05 18:47:47 【问题描述】:

如何从 php 获取实时输出?无需将所有内容存储在内存/缓冲区中并立即将所有内容回显到浏览器?

如果我创建一个 realtime-echo.php

<?php
for($i = 0; $i < 10; $i++)

echo $i;
sleep(1);

并从 Internet 浏览器访问它,它会在 9-10 秒后给出以下输出。

0123456789

但我愿意输出的是,当我从浏览器访问 php 文件时,它应该给出

0

然后等待 1 秒,然后在“0”之后添加“1” 然后等待 1 秒,然后在“1”之后添加“2” 等等。

idk 什么叫做动画/实时。

如何做到这一点?

我正在做一个项目,我需要在它发生时持续输出,这样我就可以密切关注正在发生的事情以及它的去向。

谢谢

【问题讨论】:

【参考方案1】:

如果您希望显示当前输出,请使用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();

?>

【讨论】:

我在我的 WAMP 上尝试了你的第一个代码,等待 10 秒后它立即全部运行,我正在尝试你的第二个代码 好的,让我再修改一下。 还是一样,我想我错过了什么,我什至添加了 // 关闭输出缓冲 ini_set('output_buffering', 'off'); // 关闭 PHP 输出压缩 ini_set('zlib.output_compression', false); @AmbroseBwangatto,这段代码应该可以工作。但这也与您的网络服务器有关。 php.net/manual/en/function.flush.php 这对我有用:'。 $i 。 '';冲洗(); ?>【参考方案2】:

PHP 是一种解释型服务器语言。使用 PHP,您可以创建一些本地程序或实现 Web 应用程序的服务器端。如果您在命令行中运行 PHP 代码,那么您的代码应该可以按预期工作。但是,如果您通过浏览器使用 PHP,那么 HTTP 有一个适用的请求-响应策略。如果您向浏览器发送请求,那么您只会在脚本执行时收到服务器的响应。因此,您通过浏览器请求页面,然后等待响应。服务器收到请求并回显十个数字,它们之间有第二次睡眠。 服务器完成其工作后,它会将响应发送回您的浏览器,浏览器将一次性获取十个数字。这就是为什么您会遇到等待十秒钟然后立即显示所有输出的原因:这是因为服务器执行了睡眠并收集了您的回声,然后将它们发送回刚刚显示它的浏览器。

当然,如果您想在浏览器中显示十个服务器响应,那么您必须做得更好。也许您可以使用polling(使用javascriptsetIntervalsetTimeout 函数,您正在等待在您的客户端几秒钟,然后使用@ 将发布请求发送到服务器例如,987654324@。在服务器上,您处理请求并以正确的输出响应。您的客户端应该有一个回调,您可以在其中处理服务器的响应并相应地显示它)。

【讨论】:

这是否意味着 flush() 不符合我的要求?如果能解决问题,我也可以使用 ajax。谢谢 睡眠方法在你的回声之间成功睡眠。然而,问题是 PHP 脚本执行后,PHP 会将答案发送回用户计算机上运行的浏览器,因此您等待 10 秒而没有看到任何显示,然后,响应到达并立即显示所有内容。 @LajosArpad,我相信您评论了 sleep(),而 AMB 在他的评论中询问了 flush()。我支持他的问题:Paul 的 flush() 和 ob_flush() 方法对我有用。但你的回答暗示它实际上不应该。请澄清。 @texnic 我解释了 AMB 描述的行为的原因。 flush 和 ob_flush 尝试将当前内容发送到客户端。【参考方案3】:

可能会打开输出缓冲,这会阻止实时输出。 因此,您需要将echoflush()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 />';

我试图创建一个小提琴,但sleep() 不允许在小提琴中使用。所以我创建了一个GIF。

【讨论】:

我使用 node.js 测试了您的示例以从 PHP 获取流,看起来这确实有效。但是,我的网络服务器被配置为发送更大的块,因此流式传输可能并不总是立即可见 @AdamF 在我的服务器上的php.ini 中,我有这样的 output_buffering 指令:output_buffering = 4096。您如何处理您描述的流式传输问题? @Julian,不知道这是否有帮助,但是如果您需要在代码本地更改ini设置,您可以添加这样的一行:ini_set('output_buffering', 512);

以上是关于如何在发生时从 php 获取实时输出?的主要内容,如果未能解决你的问题,请参考以下文章

如何从进程中获取实时、非阻塞的输出

针对人群的聚类分析

实时更新 GUI

如何从 php 获取输出到 typeahead?

如何使用 php 和 AJAX 绘制实时图形?

如何从 php 中列出的数组中获取 xml 输出?