【问题标题】:Cakephp cron job to call a controller's actionCakephp cron 作业来调用控制器的动作
【发布时间】:2012-06-29 17:34:39
【问题描述】:

几个月前我开始使用 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 (email.php) 来调用 /app/vendors/shells/ 中的操作。

<?php

class EmailShell extends Shell {

    public function main() {
        $this->out('Test');
    }

}
?> 

这在控制台中成功输出了测试

蛋糕电子邮件主要

但是我找不到如何调用控制器的操作。我试过了

$this->requestAction('/controller/action');

我还尝试从与 shell 中的 main 不同的函数进行调用。

我尝试将控制器包含在 $uses 变量中,就像使用模型一样,但这没有用(我认为这没有意义)

我不认为创建任务是解决方案,因为我不想复制 sendEmails 函数,因此我为什么要寻找一种方法来从 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


编辑:澄清一些信息并添加解决方案

【问题讨论】:

    标签: php shell cakephp controller cron


    【解决方案1】:

    其实这是一个很常见的问题,也遇到过。

    控制器正在决定如何处理请求并启动该任务。在这种情况下,不需要控制器,因为您有一个 shell 任务,任务已经很明确了。

    知道了,调用控制器方法是没有意义的。

    所以重新考虑你的选择,是的,这是一个相当困难的选择。例如,您可能决定发送电子邮件是一个业务逻辑步骤,因此它应该在模型中。另一种选择是将其完全分开(这是我们最喜欢的)。

    在这种情况下,您必须创建一个队列,将所有要发送的电子邮件放入其中。这是一个很好的设计,因为您知道控制器中的逻辑数量下降并且它是分离的。这样您就可以获得电子邮件服务。

    例如,您可以要求服务发送“新用户”邮件。然后将 User 对象添加到它,它应该自己处理。这样您甚至可以扩展,因为您的服务可以外包,您可以在服务上扩展多个服务器等。

    编辑:

    好问题。

    采取的步骤:

    1. 首先集中“发送电子邮件”流程。所以选择一个放置它的位置。您可以决定:添加以将电子邮件发送到队列或直接调用服务。例如,您可以添加用于发送电子邮件的 shell 任务。

    2. 调用 shell:现在你遇到了调用 shell 的问题。一般来说,你不想。为什么不?因为一个shell(一个任务)可以运行很长时间。这就是我们在两者之间使用队列的原因。所以你可以询问队列或让队列告诉你某事已经完成。例如,考虑一个已关闭的邮件服务器。您必须重试等。这不应该出现在网络请求中,因为用户正在等待响应。

    3. 第三步是从你的 cron 调用 shell,现在这很容易,因为你已经在命令行上,所以你可以使用标准调用。

    无论如何,有一些选项可以从控制器直接调用,但你不应该这样做。这篇文章提供了一些非常有趣的见解: CakePHP: Run shell job from controller

    编辑 31/08/'13:参见 CakePHP 的事件系统也有一些例子:http://book.cakephp.org/2.0/en/core-libraries/events.html

    【讨论】:

    • 我还需要能够手动调用此操作(例如,通过单击视图中的按钮)。您是否建议我创建一个任务而不是控制器操作并调用它(自动使用 cron 作业并手动单击)?您所说的外壳是与逻辑完全分离的,还是您在谈论队列?有时我需要一次发送多封电子邮件(当它被自动检查时),但它不应该经常发生,所以我想知道队列是否有点过于复杂,无法满足我的需求!谢谢你的回答
    • 也回答了他们,一般来说你应该考虑你的应用程序的大小和它的设计。我回答你问题的方式是应该做的方式之一。并不意味着这是对企业有利的方式。如果您有时只是发送邮件,则可能不值得为其创建完整且更复杂的设置。
    • 再次您好,感谢您的详细回答。我们同意不需要手动发送电子邮件,所以我创建了一个发送电子邮件的 shell。这也迫使我将更多的方法从控制器转移到模型,如果我理解得很好,这会更合适。然后我按照以下程序设置 cron 作业:book.cakephp.org/2.0/en/console-and-shells/cron-jobs.html 我决定不使用队列,尽管这看起来很有趣,因为在这种情况下不值得!
    • 不客气。很高兴看到答案真的习惯于从不同的角度考虑案例,支持一个好的解决方案,而不是仅仅用一些代码来回答!
    【解决方案2】:

    根据需要做什么,我经常将这些方法保留在我的控制器操作中。在操作的顶部,我检查 $_SERVER['REMOTE_ADDR'] == $_SERVER['SERVER_ADDR'] 以确保只有网站可以调用该操作。然后在 cron 中我会 curl 或 wget 这个地址。

    它有它的好处——在开发过程中更容易在本地运行(只需在浏览器中输入 url),另外运行 cli 版本的 php 和 apache 版本之间存在一些差异,以及请求变量(例如 cake 可以'不要通过 cli 获取网站域/地址,就像您可以作为 apache 模块运行一样,因此使用 html 帮助程序的网站的绝对链接不起作用)。

    【讨论】:

    • 我只是尝试获取地址,但它似乎没有按照我想要的方式执行操作,我可能做错了。不过,还没有尝试将它放在 crontab 中,我想我将来应该对此进行更多试验。谢谢,对不起,我不能给你打分,我还是这个网站的新手。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    相关资源
    最近更新 更多