模块结构

在YII中,程序入口是一个继承CApplication的CWebApplication的应用程序,在一个web请求的整个过程中,
控制器,模型和视图都是由Application进行创建和控制。首先我们来看一下CWebApplication的类的继承结构:

子模块的systemScope依赖 怎么打包进来_yii

从上面我们可以看到CWebApplication本身也是一个CModue。在YII中,模块之间是一个树形结构。
即每一个模块都可以包含多个子模块,每一个子模块可以继续包含子模块.其中APP为树的头节点,如图:

子模块的systemScope依赖 怎么打包进来_module_02

对于一个具体请求,假设route=A/B/C/D,下面我们讲述一下,APP怎么选择相应的模块和
模块中的控制器Controller和动作Action。具体的流程图如下:

子模块的systemScope依赖 怎么打包进来_yii_03


子模块的systemScope依赖 怎么打包进来_yii_04

对于读过YII源码都直到,任何一个web请求都是通过CApplication::Run()函数开始,进入
到CWebApplication::processRequest()。源码分别如下:

子模块的systemScope依赖 怎么打包进来_module_05

程序真正的进行到相应模块,控制器,动作是在函数processRequest的$this->runController($route);中,
该函数传入的参数为$route。何为 $route。其实$route是一个类似A/B/C/D格式的字符串,
该字符串中可能包含了模块,控制器,动作和$_GET相关参数。该函数是也是定义在CWebApplication中。代码如下:

子模块的systemScope依赖 怎么打包进来_module_06

通过该函数的名称字面意思为"运行控制器"。因此首先第一步就是要创建一个控制器,即函数createController($route)。
我们知道控制器的是包含在模块中,因此也在该函数中,通过分析$route可以得到相应的模块,以及模块中的控制器和相应的动作,
即list($controller,$actionID)=$ca;上面的流程图即为该函数createController($route)的函数流程图。
现在应该清楚了一个模块是怎么被web用户所调用了吧。下面我们说一下程序怎么在应用程序中添加模块,
当然可能是通过配置文件。

添加模块

子模块的systemScope依赖 怎么打包进来_初始化_07


子模块的systemScope依赖 怎么打包进来_初始化_08


子模块的systemScope依赖 怎么打包进来_初始化_09


模块源码分析

子模块的systemScope依赖 怎么打包进来_自定义_10


子模块的systemScope依赖 怎么打包进来_加载_11


子模块的systemScope依赖 怎么打包进来_加载_12

public function __construct($id,$parent,$config=null)//$id为模块ID,$parent为父模块ID  
{  
    $this->_id=$id;  
    $this->_parentModule=$parent;  
    // set basePath at early as possible to avoid trouble  
    if(is_string($config))  
        $config=require($config);  
    if(isset($config['basePath']))  
    {  
        $this->setBasePath($config['basePath']);//设置模块路径  
        unset($config['basePath']);  
    }  
    Yii::setPathOfAlias($id,$this->getBasePath());//把该模块的路径添加到Alias中,方便访问  
    //下面几个函数就是模块的初始化需要做的几件事情,可以通过重写preinit()和init()来自定义模块可以通过自定义相应的函数来定制和初始化模块的参数  
        $this->preinit();//预初始化,一般用来设置模块相关的行为对象$behaviors[],预加载对象$preload[],和其他配置。  
    $this->configure($config);//加载配置  
    $this->attachBehaviors($this->behaviors);//挂载行为对象  
    $this->preloadComponents();//加载CModule::$preload[]中的预加载组件  
    $this->init();//模块真正初始化,一般情况下,重写该函数完整模块初始化  
}

CWebModule分析

子模块的systemScope依赖 怎么打包进来_加载_13

public function beforeControllerAction($controller,$action)  
{  
    if(($parent=$this->getParentModule())===null)  
        $parent=Yii::app();  
    return $parent->beforeControllerAction($controller,$action);  
}  

public function afterControllerAction($controller,$action)  
{  
    if(($parent=$this->getParentModule())===null)  
        $parent=Yii::app();  
    $parent->afterControllerAction($controller,$action);  
}
可以通过此两个函数对该模块中的每一个请求进行一些改写,控制以及收尾的相关工作。在自定义的模块中,
两个函数的覆盖的模版如下:

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;  
}

子模块的systemScope依赖 怎么打包进来_自定义_14


子模块的systemScope依赖 怎么打包进来_加载_15


子模块的systemScope依赖 怎么打包进来_初始化_16


子模块的systemScope依赖 怎么打包进来_加载_17


子模块的systemScope依赖 怎么打包进来_加载_18


子模块的systemScope依赖 怎么打包进来_自定义_19

array(

      'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',//模块的路径

      'preload'=>array('log'),//需要预先加载日志组件

      'import'=>array('application.models.*', 'application.components.*',),//需要include的路径

      //组件的配置

      'components'=>array(

           'user'=>array(//用户组件的配置

                 'allowAutoLogin'=>true

                 ),

           'log'=>array(//日志组件的配置

                 'class'=>'CLogRouter',

                 'routes'=>array(array('class'=>'CWebLogRoute','levels'=>'trace, profile'))

                 )

      ),

      //模块的配置

      'modules'=>array(

           'gii'=>array(//自动生成代码模块的配置

                 'class'=>'system.gii.GiiModule',

                 'password'=>'123456'

           ),

      ),

);