几个月前我开始使用CakePHP(1.2)为公司的应用程序添加小功能,但我不太熟悉它。
我们在本地进行测试,然后在合并到生产服务器之前在开发服务器上进行测试。
我希望每小时调用一次控制器操作,我认为这是通过我的研究做到这一点的最佳方式,即 cron 工作。
尝试 1
看完这些,
http://bakery.cakephp.org/articles/mathew_attlee/2006/12/05/calling-controller-actions-from-cron-and-the-command-line
http://book.cakephp.org/1.2/en/view/110/Creating-Shells-Tasks
我可以毫无错误地实现一些东西,但该操作未执行。
基于这些示例,我在我的应用程序目录(不是 app/webroot)中添加了一个名为 cron_dispatcher.php 的文件,然后从应用程序目录执行此命令
PHP cron_dispatcher.php/controller/action/param
仍然什么也没发生,但是当我通过 url 调用它时,它工作得很好。
尝试 2
我尝试创建一个 shell(电子邮件.php),它会在/app/vendors/shells/中调用该操作。
<?php
class EmailShell extends Shell {
public function main() {
$this->out('Test');
}
}
?>
这将使用
蛋糕电子邮件主
但是我找不到如何调用控制器的操作。我试过了
$this->requestAction('/controller/action');
我还尝试从与 shell 中的 main 不同的函数进行调用。
我试图像使用模型一样将控制器包含在$uses变量中,但这不起作用(我认为这没有意义)
我不认为创建任务是解决方案,因为我不想复制 sendEmail 函数,因此我正在寻找一种仅从 shell 或其他任何东西调用控制器操作的方法!
可能我缺少一些理论,谢谢
溶液
我将一些方法从控制器移动到模型,并且能够从 shell 调用它们。
App::import('Component', 'Email');
class SendMemosShell extends Shell {
var $uses = array(
'Memo',
);
public function main() {
}
public function sendEmails () {
$this->Email =& new EmailComponent(null);
$memoList = $this->Memo->getMemos();
//...
}
}
此链接有所帮助http://book.cakephp.org/2.0/en/console-and-shells/cron-jobs.html
编辑:澄清了一些信息并添加了解决方案
很常见的问题,也遇到了。
控制器正在决定如何处理请求并启动该任务。在这种情况下,不需要控制器,因为您有一个 shell 任务,任务已经很清楚了。
知道这一点,调用控制器方法没有意义。
因此,请重新考虑您的选择,是的,这是一个非常困难的选择。例如,您可能决定发送电子邮件是一个业务逻辑步骤,因此它应该在模型中。另一种选择是将其完全分开(这是我们最喜欢的)。
在这种情况下,您必须创建一个队列,在其中输入要发送的所有电子邮件。这是一个很好的设计,因为您知道控制器中的逻辑量下降并且它是分开的。这样您就可以获得电子邮件服务。
例如,您可以要求服务发送"新用户"邮件。然后,将 User 对象添加到其中,它应该自行处理。这样,您甚至可以扩展,因为例如您的服务可以外包,您可以在服务上扩展多个服务器等。
编辑:
好问题。
要采取的步骤:
首先集中"发送电子邮件"过程。因此,选择一个放置它的位置。您可以决定:添加以将电子邮件发送到队列或直接调用服务。例如,您可以添加用于发送电子邮件的 shell 任务。
调用外壳:现在您遇到了调用外壳的问题。一般来说,你不想。为什么不呢?因为外壳(任务)可以运行很长时间。这就是为什么我们在两者之间使用队列。因此,您可以询问队列或让队列向您发送消息,说明已完成某些操作。例如,考虑一个关闭的邮件服务器。您必须重试等。这不应该在 Web 请求中,因为用户正在等待响应。
第三步是从你的 cron 调用 shell,现在这很容易,因为你已经在命令行上,所以你可以使用标准调用。
无论如何,有一些选项可以从控制器进行直接调用,但您不应该这样做。这篇文章给出了一些非常有趣的见解:CakePHP:从控制器运行 shell 作业
编辑 31/08/'13:参见 CakePHP 的事件系统,也有一些例子: http://book.cakephp.org/2.0/en/core-libraries/events.html
根据需要执行的操作,我经常将这些方法保留在控制器操作中。在操作的顶部,我检查 $_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR'] 以确保只有网站可以调用该操作。然后在 cron 中,我会卷曲或获取此地址。
它有它的好处 - 在开发过程中更容易在本地运行(只需在浏览器中输入 url),此外运行 cli 版本的 php 和 apache 版本以及请求变量之间存在一些差异(例如,cake 无法像您可以作为 apache 模块运行一样通过 cli 获取网站域/地址,因此使用 html 助手指向网站的绝对链接不起作用)。