0

我想要实现的是创建一个高度模块化的应用程序。我正在尝试创建一个 cron 脚本来解决需要在所有子模块中触发的所有 cron 脚本。我实际上想做的是创建一个事件,说它runCron从 a 中触发CController,然后当它从子模块中使用onRunCron方法引发时挂钩到该事件中。概述我正在尝试做的事情:

Application
|- CronController.php - Raise the event 'RunCron', not knowing which modules will fire after this.
|- Modules
   |- Nodes 
      |- Observe the event 'onRunCron' and run own cron script
   |- Users
      |- Observe the event 'onRunCron' and run own cron script

根据 Yii 的事件系统,我认为我需要做的是创建事件并在应用程序级别引发它(这仍然是我想要做的)但是然后;我还需要在控制器的应用程序级别分配来自子模块的回调。这是我不想要的,因为当添加/删除子模块时,需要调整应用程序,这听起来根本不是模块化的。

有人可以列出设置这样的活动并使其尽可能模块化的基础知识吗?因为我认为我在看这个完全错误的方式。

编辑(解决方案):

感谢acorncom 的回答,我设法制定了以下系统。

application.components.CronSingleton

<?php

class CronSingleton extends CApplicationComponent {

    /**
     * Make sure we "touch" the modules, so they are initialised and are able to attach their listeners.
     */
    public function touchModules () {
        $modules = Yii::app()->getModules();

        if (!empty($modules)) {
            foreach ($modules as $name => $module) {
                Yii::app()->getModule($name);
            }
        }
    }

    /**
     * This method should be run to run the cron. It will commense all the procedures in cronjobs
     */
    public function execCron($caller) {
        $this->touchModules();
        $this->onStartCron(new CEvent($caller));
        $this->onRunCron(new CEvent($caller));
        $this->onExitCron(new CEvent($caller));
    }

    /**
     * Raise an event when starting cron, all modules should add their listeners to this event if they would like to fire something before running the cron.
     */
    public function onStartCron ($event) {
        $this->raiseEvent('onStartCron', $event);
    }

    /**
     * Raise an event when running cron, all modules should add their listeners to this event to execute during cron run. Mosty this event should be used.
     */
    public function onRunCron ($event) {
        $this->raiseEvent('onRunCron', $event);
    }

    /**
     * Raise an event when cron exits, all modules should add their listeners to this event when cron exits.
     */
    public function onExitCron ($event) {
        $this->raiseEvent('onExitCron', $event);
    }
}

?>

application.controllers.CronController

<?php

class CronController extends Controller
{

    public $layout='//layouts/bare';

    public function actionIndex($k) {
        Yii::app()->cron->onStartCron = array($this, 'startcron');
        Yii::app()->cron->onRunCron = array($this, 'runcron');
        Yii::app()->cron->onExitCron = array($this, 'exitcron');
        Yii::app()->cron->execCron($this);
    }

    public function startcron(){
        var_dump('CronController - Starting cron');
    }

    public function runcron(){
        var_dump('CronController - Run cron');
    }

    public function exitcron(){
        var_dump('CronController - Ending cron');
    }
}

?>

application.modules.admin.AdminModule

<?php

class AdminModule extends CWebModule
{
    public function init()
    {
        // this method is called when the module is being created
        // you may place code here to customize the module or the application

        // import the module-level models and components
        $this->setImport(array(
            'admin.models.*',
            'admin.components.*',
        ));

        Yii::app()->cron->onRunCron = array($this, 'runCron');
    }

    public function runCron($event) {
        var_dump('AdminModule - Run cron');
    }

    public function beforeControllerAction($controller, $action)
    {
        if(parent::beforeControllerAction($controller, $action))
        {
            // this method is called before any module controller action is performed
            // you may place customized code here
            return true;
        }
        else
            return false;
    }
}
?>

这个“概念证明”设置设法打印出以下结果,正是我想要它做的:

string(30) "CronController - Starting cron"
string(25) "CronController - Run cron"
string(22) "AdminModule - Run cron"
string(28) "CronController - Ending cron"
4

2 回答 2

1

我认为你会想要做类似以下的事情(注意:这还没有经过测试,但它应该在概念上工作)。

  1. 为您的 cron 系统创建一个 CApplicationComponent。让它成为一个应用程序组件(在您的 config/main.php 文件中注册)使其可以从您的应用程序/模块/子模块/控制器等中的任何位置访问

  2. 让您的 cron 组件处理事件的注册/事件的触发。请参阅 Yii 事件页面以获取有关其工作原理的详细信息。注意:如果您需要传入有关事件的其他参数,您可以创建自己的自定义事件,将主 CEvent 类作为子类。

  3. 让您的模块在初始化时注册为您的 cron 组件的事件处理程序。

  4. 让您的控制器向您的 cron 组件触发一个事件。

一个潜在的陷阱。我不确定是先注册模块还是组件(我相信组件应该是,但值得测试)。如果您的 cron 组件在尝试向您的 cron 组件注册事件的模块之后加载,那么您可能需要预加载您的 cron 组件。如果不起作用,您可以尝试其他一些技巧(回来询问更多详细信息)。

哦,让我们知道进展如何!

于 2013-03-05T03:34:51.660 回答
0

你查看过 yii 网站上关于事件的 wiki 吗?我认为这是一个很好的起点,如果您仍有问题,我们可以帮助您!

于 2013-02-26T17:16:34.440 回答