使用Zend Framework创建cronjob
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Zend Framework创建cronjob相关的知识,希望对你有一定的参考价值。
我正在尝试编写一个cronjob控制器,所以我可以调用一个网站并执行所有模块cronjob.php。现在我的问题是我该怎么做?
卷曲是一种选择,所以我也可以计算错误和成功吗?
[更新]
我想我还没有解释得够。
我想做的是有一个文件,我可以从http://server/cronjob调用,然后让它执行每个/application/modules/*/controller/CronjobController.php或有另一种方式这样做所以所有的cronjobs不在一个放置在模块所在的同一个地方。这将为我提供优势,如果模块不存在,它不会尝试运行其cronjob。
现在我的问题是你将如何执行CronjobController的所有模块,或者你会以完全不同的方式执行它,因此它仍然保持模块化?
我希望能够发出有多少cron作业成功运行,有多少没有
经过一些研究和拖延很多我得出了一个简单的结论:ZF-ized cron脚本应该包含你zend框架应用程序的所有功能 - 没有所有视图的东西。我通过在我的应用程序目录中创建一个新的cronjobfoo.php文件来完成此操作。然后我从以下方面采取了最低限度:-my前端控制器(index.php)-my bootstrap.php
我拿出所有视图的东西,专注于保持环境设置,数据库设置,自动加载器和注册表设置。我不得不花一点时间来纠正文档根变量并删除从我的引导程序复制的一些OO功能。
之后,我只是编码了..在我的情况下,它正在编译并通过电子邮件发送夜间报告。使用Zend_Mail非常棒。当我确信我的脚本按照我想要的方式工作时,我只是添加了我的crontab。
祝好运!
您可以设置一个数据库表来保存对cronjob脚本的引用(在您的模块中),然后使用带有pass / fail返回值的exec命令。
我用Zend_Test_PHPUnit
扩展了gregor的答案。这是出来的:
this post
谢谢格雷戈尔!
我的解决方案
- 卷曲/ cron
- 全局cron方法将包括所有控制器
- 检查每个控制器是否具有 - > cron方法
- 如果他们有,运行那些。
公共cron url(用于curl)不是问题,有很多方法可以避免滥用。如上所述,检查远程IP是最简单的。
这是我用Zend Framework运行Cron Jobs的方法
在Bootstrap中,我将保持环境设置,因为它是负MVC:
//public/index.php
// Run application, only if not started from command line (cli)
if (php_sapi_name() != 'cli' || !empty($_SERVER['REMOTE_ADDR'])) {
$application->run();
}
同样在Bootstrap中,我将修改setupRoutes并添加自定义路由:
public static function setupEnvironment()
{
...
self::setupFrontController();
self::setupDatabase();
self::setupRoutes();
...
if (PHP_SAPI !== 'cli') {
self::setupView();
self::setupDbCaches();
}
...
}
App_Router_Cli是一种新的路由器类型,它根据此类请求确定控制器,操作和可选参数:public function setupRoutes()
{
...
if (PHP_SAPI == 'cli') {
self::$frontController->setRouter(new App_Router_Cli());
self::$frontController->setRequest(new Zend_Controller_Request_Http());
}
}
。我在这里找到了这个新的路由器:script.php controller=mail action=send
:
Setting up Cron with Zend Framework 1.11
在CronController中,我做了一个简单的检查:
class App_Router_Cli extends Zend_Controller_Router_Abstract
{
public function route (Zend_Controller_Request_Abstract $dispatcher)
{
$getopt = new Zend_Console_Getopt (array());
$arguments = $getopt->getRemainingArgs();
$controller = "";
$action = "";
$params = array();
if ($arguments) {
foreach($arguments as $index => $command) {
$details = explode("=", $command);
if($details[0] == "controller") {
$controller = $details[1];
} else if($details[0] == "action") {
$action = $details[1];
} else {
$params[$details[0]] = $details[1];
}
}
if($action == "" || $controller == "") {
die("Missing Controller and Action Arguments == You should have:
php script.php controller=[controllername] action=[action]");
}
$dispatcher->setControllerName($controller);
$dispatcher->setActionName($action);
$dispatcher->setParams($params);
return $dispatcher;
}
echo "Invalid command.
", exit;
echo "No command given.
", exit;
}
public function assemble ($userParams, $name = null, $reset = false, $encode = true)
{
throw new Exception("Assemble isnt implemented ", print_r($userParams, true));
}
}
Crontab运行这种命令:
public function sendEmailCliAction()
{
if (PHP_SAPI != 'cli' || !empty($_SERVER['REMOTE_ADDR'])) {
echo "Program cannot be run manually
";
exit(1);
}
// Each email sent has its status set to 0;
在同一目录或cron作业文件夹中运行引导程序没有意义。我已经创建了一种更好,更简单的方法来实现cron作业。请按照以下方式使您的工作变得轻松和聪明:
- 无论你想要什么,创建一个cron作业文件夹,如“cron”或“crobjob”等。
- 有时我们需要cron作业在不同间隔的服务器上运行,例如1小时间隔或1天间隔,我们可以在服务器上设置。
- 在cron job文件夹中创建一个文件,就像我创建了一个“init.php”,现在让我们假设您想每天向用户发送一次简报。您不需要在init.php中执行zend代码。
- 所以只需在init.php中设置curl函数,并在该curl函数中添加控制器动作的URL。因为我们的主要目的是每天都应该调用一个动作。例如,URL应如下所示:
* * * * * php /var/www/projectname/public/index.php controller=name action=send-email-cli >> /var/www/projectname/application/data/logs/cron.log
因此,在curl函数中设置此URL,并在同一文件中的init.php中调用此函数。
在上面的链接中,您可以看到“cron”是控制器,而新闻简报是您可以执行工作的操作,同样,不需要运行引导程序文件等。
对于Zend Framework,我目前正在使用下面概述的代码。该脚本仅包含门户文件index.php,其中所有路径,环境和其他Zendy代码都是自举的。通过在cron脚本中定义一个常量,我们取消了运行应用程序的最后一步。
这意味着应用程序只是设置,甚至没有自举。在这一点上,我们开始引导我们需要的资源,就是这样
//public/index.php
if(!defined('DONT_RUN_APP') || DONT_RUN_APP == false) {
$application->bootstrap()->run();
}
// application/../cron/cronjob.php
define("DONT_RUN_APP",true);
require(realpath('/srv/www/project/public/index.php'));
$application->bootstrap('config');
$application->bootstrap('db');
//cron code follows
我会提醒你的cronjobs可以向公众开放,因为它们可以在正常时间之外被触发,并且取决于它们的作用,会导致问题(我知道这不是你想要的,但是把它们放到一个实际的控制器中就可以到达了来自浏览器)。例如,我有一个发送电子邮件的cron。如果有人找到了cron URL并且刚刚开始点击它,我会不断发送垃圾邮件。
我做的是创建一个cron文件夹,并在那里创建了一个heartbeat.php,它为我引导了Zend Framework(减去MVC)。它检查一个数据库,该数据库包含所有已安装的cron作业的列表,如果是时候运行它们,则生成一个cron作业类的实例并运行它。
cron作业只是来自抽象cron类的子类,它具有install(),run(),deactivate()等方法。
为了解雇我的工作,我只有一个简单的crontab条目,每隔5分钟就会运行一次,命中heartbeat.php。到目前为止,它在两个不同的网站上都很棒。
几天前有人提到this blog entry关于fw-general(我建议你在使用Zend Framework时阅读的mailinglist)。
还有一个Zend_Controller_Request_Cli的提案,迟早要解决这个问题。
我可以访问专用服务器,我最初为cron作业提供了不同的引导程序。我最终讨厌这个想法,只是希望我能在现有的MVC设置中做到这一点,而不必费心去处理事情。
我创建了一个文件cron.sh,保存在我的站点root(不公开)中,并在其中我放了一系列我想运行的命令。因为我想立即运行许多命令,我像往常一样在我的控制器中编写PHP,并在cron.sh中添加了对这些URL的curl调用。例如curl http://www.mysite.com/cron_controller/action
然后在cron界面上我跑了bash /path/to/cron.sh
。
正如其他人所指出的那样,任何猜测网址的人都可以解雇你的crons,所以总会有警告。您可以通过多种方式找到解决方案。
看看zf-cli
:
这可以很好地处理所有cron作业。
为什么不创建一个crontab.php,包括或需要index.php引导程序文件?
考虑到引导程序正在执行Zend_Loader::registerAutoload()
,您可以直接开始使用模块,例如,myModules_MyClass::doSomething();
这样你就可以跳过控制器了。 Controller作业是通过http控制访问。在这种情况下,您不需要控制器方法,因为您正在本地访问。
qazxsw poi我通过googleing找到的这个链接似乎也很有趣。
它不是我想要的安静,但如果我似乎无法找到我想要的东西,我将不得不自己。
你有文件系统访问模块的目录吗?您可以迭代目录并确定CronjobController.php可用的位置。然后你可以使用http://framework.zend.com/wiki/display/ZFPROP/Zend_Scheduler+-+Matthew+Ratzloff?rootCommentId=1819
以上是关于使用Zend Framework创建cronjob的主要内容,如果未能解决你的问题,请参考以下文章
Zend Framework windows8.1下配置zend framework1.12
如何在控制器或视图之外使用 Zend Framework 部分视图助手?
让 Zend Framework 2 Memcached 工作