Module 构建基于事件的应用程序范围的cron组件

Module 构建基于事件的应用程序范围的cron组件,module,yii,yii-events,Module,Yii,Yii Events,我试图实现的是创建一个高度模块化的应用程序。我正在尝试创建一个cron脚本,它处理所有子模块中需要触发的所有cron脚本。实际上,我想做的是创建一个事件,比如说runCron,它从CController触发,然后当它从子模块中使用onRunCron方法引发时挂接到该事件中。概述我正在尝试做的事情: Application |- CronController.php - Raise the event 'RunCron', not knowing which modules will fire a

我试图实现的是创建一个高度模块化的应用程序。我正在尝试创建一个cron脚本,它处理所有子模块中需要触发的所有cron脚本。实际上,我想做的是创建一个事件,比如说
runCron
,它从
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的事件系统,我认为我需要做的是创建事件并在应用程序级别提升它(这仍然是我试图做的),但是;我还需要在控制器的应用程序级别上分配来自子模块的回调。我不希望这样,因为当一个子模块被添加/删除时,应用程序需要调整,这听起来根本不是模块化的

有没有人能列出建立这样一个活动并使其尽可能模块化的基础知识?因为我觉得我完全错了

编辑(解决方案):

多亏了你,我终于想出了下面的办法

应用程序.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);
    }
}

?>

你查过yii网站上关于事件的维基吗?我认为这是一个很好的开始,如果你还有一些问题,我们可以帮助你


我想你会想做如下的事情(注意:这还没有经过测试,但在概念上应该是可行的)

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

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

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

  • 让控制器向cron组件触发事件

  • 一个潜在的陷阱。我不确定模块或组件是否首先注册(我认为组件应该注册,但值得测试)。如果您的cron组件是在尝试向cron组件注册事件的模块之后加载的,那么您可能需要预加载cron组件。如果这不起作用,你还可以尝试其他一些黑客(回来询问更多细节)


    哦,让我们知道进展如何

    感谢您对这个问题的理解。我会在这周的某个时候再次参与这个项目,我会让你知道这是否可行,但它有声音,因为这是我想要的,谢谢!如果您发现这确实解决了您的问题,请接受。
    <?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');
        }
    }
    
    ?>
    
    <?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"