我可以像register_shutdown_function一样使用fastcgi_finish_request()吗?

时间:2013-02-15 20:34:57

标签: fastcgi php

这种用于缓存动态内容的简单方法使用register_shutdown_function()在退出脚本后将输出缓冲区推送到磁盘上的文件。但是,我正在使用 PHP-FPM ,但这不起作用;添加到该函数的5秒睡眠确实会导致从浏览器执行脚本延迟5秒。 PHP文档中的一位评论者指出,PHP-FPM用户有一个特殊的功能,即fastcgi_finish_request()。但是,这个特定功能的文档并不多。

fastcgi_finish_request()似乎是要刷新所有数据并继续执行其他任务,但我想要实现的目标(通常与register_shutdown_function()一起使用)基本上是将内容放在输出缓冲区到文件中,用户不必等待它完成。

有没有办法在PHP-FPM下使用fastcgi_finish_request()或其他函数实现这一目标?

$timeout = 3600; // cache time-out
$file = '/home/example.com/public_html/cache/' . md5($_SERVER['REQUEST_URI']); // unique id for this page
if (file_exists($file) && (filemtime($file) + $timeout) > time()) {
  readfile($file);
  exit();
} else {
  ob_start();
  register_shutdown_function(function () use ($file) {
    // sleep(5);
    $content = ob_get_flush();
    file_put_contents($file, $content);
  });
}

3 个答案:

答案 0 :(得分:3)

是的,可以使用fastcgi_finish_request。您可以保存此文件并查看其是否有效:

<?php

$timeout = 3600; // cache time-out
$file = '/home/galymzhan/www/ps/' . md5($_SERVER['REQUEST_URI']); // unique id for this page
if (file_exists($file) && (filemtime($file) + $timeout) > time()) {
  echo "Got this from cache<br>";
  readfile($file);
  exit();
} else {
  ob_start();
  echo "Content to be cached<br>";

  $content = ob_get_flush();
  fastcgi_finish_request();
  // sleep(5);

  file_put_contents($file, $content);
}

即使您使用sleep(5)取消注释该行,您也会看到该页面仍然会立即打开,因为fastcgi_finish_request会将数据发送回浏览器,然后继续执行之后编写的任何代码。

答案 1 :(得分:1)

首先, 如果以这种方式缓存动态内容,那么你做错了。当然它可以这样使用,它可以工作,但它完全瘫痪的方法本身。

如果你想有效地缓存和处理内容,可以创建一个类并将所有缓存函数包装成。

是的,您可以像fast_cgi_finish_request()一样使用register_shutdown()。唯一的区别是,fast_cgi_finish_request()将发送输出(如果有)并且将不会终止脚本,而在脚本终止时将调用register_shutdown()的回调。 / p>

答案 2 :(得分:0)

这是一个老问题,但我不认为任何答案都能正确回答问题。

据我了解,问题是在关闭函数期间发生的ob_get_flush()调用之前,没有任何输出被发送到客户端。

要解决该问题,您需要将函数和块大小传递给ob_start(),以便以块的形式处理输出。

你的其他条款有这样的事情:

$content = '';

$write_buffer_func = function($buffer, $phase) use ($file, &$content) {
  $content .= $buffer;
  if ($phase & PHP_OUTPUT_HANDLER_FINAL) {
    file_put_contents($file, $content);
  }
  return $buffer;
};

ob_start($write_buffer_func, 1024);