2008-11-16 69 views
4

PHP提供了一种机制来注册关闭功能:在PHP中完成HTTP请求后执行代码?

register_shutdown_function('shutdown_func'); 

的问题是,在最近的版本的PHP中,此功能仍然在请求期间执行。

我有一个平台(在Zend框架中,如果有的话)整个请求中的任何一段代码都可以注册一个条目来登录到数据库。整个请求中并没有大量的单个插入语句,而是减慢了页面的速度,我将它们排队以便在请求结束时插入。我希望在用户完成HTTP请求后能够做到这一点,因此记录或执行任何其他清理任务的时间长度不会影响用户感知的页面加载时间。

在PHP中是否有内置的方法来做到这一点?或者是否需要配置某种与外部进程共享的内存空间方案,并指示进程执行日志记录?

+0

疯狂 - 我今天早些时候会问这个问题! – 2008-11-16 03:21:34

+0

得爱的计算器! – 2008-11-16 03:33:04

回答

4

如果你真的关心MySQL的插入时间,你可能是在解决症状而不是原因。例如,如果您的PHP/Apache进程在用户获取HTML之后执行,您的PHP/Apache进程仍然被锁定到该请求中。由于它很忙,如果有另一个请求出现,Apache必须分叉另一个线程,为它提供更多内存,打开其他数据库连接等。

如果遇到性能问题,您需要删除繁重的你的PHP/Apache执行。如果你有很多清理任务正在进行,那么你正在烧制宝贵的Apache进程。

我会考虑将您的条目记录到文件中,并让crontab将这些条目加载到数据库带外。如果您有其他繁重任务,请使用排队/作业处理系统进行带外工作。

1

除了register_shutdown_function(),还没有内建确定脚本何时退出的方法。然而,Zend Framework在调度过程的特定点上有几个钩子来运行代码。 为了您的要求,最相关的将是动作控制器的post-dispatch hook,该动作控制器在发送动作后立即发生,并且dispatchLoopShutdown event用于控制器插件代理。

您应该阅读手册以确定哪种更适合您。

编辑:我想我完全不明白。从这些钩子中,您可以以某种形式或其他形式分离当前进程。 PHP有几种分叉处理方式,您可以在program execution下的手册中阅读。我会建议通过pcntl扩展 - 读this blog post来查看分支子进程在后台运行的示例。

+0

这些钩子都不能自己解决我的问题。这些挂钩仍在HTTP请求中运行。就浏览器而言,该页面仍在加载。例如,假设日志记录耗时5秒,浏览器将会看到5秒以上的加载时间。 – 2008-11-16 03:20:46

0

关于this random guy's blog的评论听起来和你想要的相似。如果该头部技巧不起作用,那么如果您的Web主机的配置允许这样的事情,则该博客上的其中一条评论建议exec()将单独的PHP脚本在后台运行。

0

这可能对你的口味有点骇人听闻,但这将是一个有效和简单的解决方法。

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

例如:

<?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. 
?> 

就像我说的,我看你怎么可以考虑这个的hackish,但框架将独立于其父页面加载,所以它会实现你想要的,而不需要在后台运行其他应用程序。

希望这至少能指引您朝着正确的方向发展。

干杯!

相关问题