在PHP中完成HTTP请求后执行代码?

在PHP中完成HTTP请求后执行代码?,php,zend-framework,Php,Zend Framework,PHP提供了一种注册关闭函数的机制: register_shutdown_function('shutdown_func'); 问题是,在PHP的最新版本中,此函数仍然在请求期间执行 我有一个平台(在Zend Framework中,如果需要的话),在这个平台上,整个请求中的任何代码都可以注册一个条目以登录到数据库中。我没有在整个请求中使用大量的insert语句,从而降低页面速度,而是将它们排队,以便在请求结束时插入。我希望能够在用户完成HTTP请求后执行此操作,以便登录或执行任何其他清理任务的

PHP提供了一种注册关闭函数的机制:

register_shutdown_function('shutdown_func');
问题是,在PHP的最新版本中,此函数仍然在请求期间执行

我有一个平台(在Zend Framework中,如果需要的话),在这个平台上,整个请求中的任何代码都可以注册一个条目以登录到数据库中。我没有在整个请求中使用大量的insert语句,从而降低页面速度,而是将它们排队,以便在请求结束时插入。我希望能够在用户完成HTTP请求后执行此操作,以便登录或执行任何其他清理任务的时间长度不会影响用户对页面的感知加载时间


PHP中是否有内置的方法来实现这一点?或者我需要用外部进程配置某种共享内存空间方案并向该进程发送信号以进行日志记录吗?

除了register\u shutdown\u function()之外,没有内置的方法来确定脚本何时退出。但是,Zend框架有几个钩子用于在分派过程中的特定点运行代码。 对于您的需求,最相关的是动作控制器,它发生在动作被调度之后,以及控制器插件代理

您应该阅读手册,以确定哪个更适合您

编辑:我想我没有完全理解。从这些钩子中,您可以以某种形式分叉当前进程。
PHP有几种分叉进程的方法,您可以在下面的手册中阅读。我建议浏览一下pcntl扩展-read,看看在后台运行分叉子进程的示例。

关于的注释听起来与您想要的类似。如果这个标题技巧不起作用,该博客上的一条评论建议
exec()
在后台运行一个单独的PHP脚本,如果您的Web主机的配置允许这样做的话。

这可能有点不合您的口味,但这将是一个有效且简单的解决方法

您可以创建一个由您选择的DB管理的“队列”,首先将请求存储在数据库中的队列表中,然后输出一个iframe,该iframe生成一个脚本,该脚本将触发与数据库中的队列id匹配的指令

例:


如果您真的关心MySQL的插入时间,那么您可能是在解决症状,而不是原因

例如,如果您的PHP/Apache进程是在用户获取HTML后执行的,那么您的PHP/Apache进程仍然锁定在该请求中。由于它很忙,如果出现另一个请求,Apache必须分叉另一个线程,为其分配更多内存,打开其他数据库连接,等等

如果遇到性能问题,则需要从PHP/Apache执行中消除繁重的工作。如果你有很多清理任务在进行,那么你正在烧掉宝贵的Apache进程


<>我会考虑把你的条目记录到一个文件中,并把一个CrutAB加载到你的数据库之外。如果您有其他繁重的任务,请使用排队/作业处理系统来完成带外工作。

这两个钩子都不能单独解决我的问题。这些钩子仍在HTTP请求中运行。就浏览器而言,页面仍在加载中。例如,假设日志记录耗时5秒,浏览器将看到5秒以上的加载时间。我明白了。我编辑了我的答案,以建议如何使用这些挂钩来满足您的需求。疯狂-我今天早些时候就想问这个问题!练习的重点是避免在连接用户浏览器时执行DB插入。如果我必须将项目插入DB中的队列中,以便稍后处理,为什么我不首先将它们放在DB中的位置?听起来您主要关心的是用户的感知加载时间。将所有这些指令卸载到iframe肯定会实现这一点。如果您不想使用数据库作为队列,请使用memcache。除了在MySQL中使用表之外,还有其他队列系统。很多都很轻。例如,请参阅Amazon SimpleDB。感谢您提及SimpleDB Gary。考虑到“D-Rock”所面临的问题,这实际上是完美的。
<?php
mysql_query('INSERT INTO queue ('instructions') VALUES ('something would go here');
echo('<iframe src="/yourapp/execute_queue/id?' . mysql_insert_id() . '" />');
?>
<?php
$result = mysql_query('SELECT instructions FROM queue WHERE id = ' . $_GET['id']);
// From here, simply execute some instruction based on the "instructions" field, then delete the instruction from the database.
?>