在启用输出缓冲的情况下检测用户中止的PHP问题

3
ignore_user_abort()的函数文档的注释中提到,如果没有向客户端发送数据,PHP无法检测到用户终止请求。这对于connection_status()函数也是正确的。不幸的是,在使用输出缓冲的页面上(我不能轻易更改),我需要检测用户中止(可以取消的ajax请求)。

除了使用connection_status()函数之外,是否有其他检测用户中止的方法?或者有没有特定的方法使该函数返回正确的值?实际上,PHP应该知道请求已被中止,因为从客户端接收到FIN包。

我已经尝试过分析php://inputphp://outputphp://stdinphp://stdout流元数据,在阻塞和非阻塞方式下读写数据以及连接中断前后,但这并没有提供任何有用的状态变化。


@tomalak - 实际上,你可以!看一下register_shutdown_function()... 你可以在这里捕获用户中止、超时、正常完成等情况... 并执行一些额外的代码逻辑。 - Mark Baker
@MarkBaker:呃,你破坏了我的讽刺回应。 - Lightness Races in Orbit
@tomalak - 或许...了解 register_shutdown_function() 函数也有助于 OP 考虑解决问题的其他方法。 - Mark Baker
@sexyprout:我需要将数据发送给客户端,register_shutdown_function() 无法帮助。 - soulmerge
@Tomalak,@MarkBaker:我所说的abort是指用户点击浏览器的停止按钮或在Javascript ajax请求对象上调用abort()(两者都会向服务器发送FIN数据包,即关闭连接)。不幸的是,只有当PHP尝试向客户端写入内容时,它才会意识到这种情况,而由于输出缓冲,我无法这样做。换句话说:如果“中止就是中止”,那我会很高兴的 :-) - soulmerge
显示剩余5条评论
1个回答

1
愚蠢的建议,但是...你尝试过在开始输出缓冲之前向客户端发送一些数据,然后再使用flush()吗?我能想到的唯一其他解决方案是转义缓冲区,但我可以想象这可能会非常麻烦,就像你说的那样。
也许有一个助手来帮助打破缓冲区...
function OBWanCallback($buffer)
{
    if( OBWan::$isFinished )
    {
        // -- Actual callbacks go here ...
    }

   return $buffer;
}

OBWan::startbuffer('OBWanCallback');
[ // -- Example functionality
    self::$callback = $callback;
    ob_start(self::$callback);
]

// -- in some code far, far away ...

OBWan::suspendbuffer();
[ // -- Example functionality
    self::$buffercache = ob_get_clean();
]

echo " ";
flush();

OBWan::resumebuffer();
[ // -- Example functionality
    ob_start(self::$callback);
    echo self::$buffercache;
    self::$buffercache = "";
]

// -- in some code far, far away ...

OBWan::outputbuffer();
[
    self::$isFinished = true;
    return ob_get_clean();
]

如果您已经实现了深度缓冲区,那么需要考虑一些东西来解决它。


如果没有其他解决方案,我会使用类似这样的方法,但这会触发所有已注册ob_start()的回调函数,带来不良影响。 - soulmerge
如果您使用助手程序,您可以非常狡猾,并编写一个回调中继函数来检查是否正在调用最终刷新。我会尝试更新示例。 - Jeff Parker
看起来非常有趣,我想我会将其集成到我们的输出缓冲管理器类中,非常感谢 :-) - soulmerge

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