你现在的位置:首页 > PHP网站建设知识库 > Yii > 正文

YII框架学习笔记:模块module

yii程序开发中,module是对相同业务逻辑的app中的内容模块化,比如博客前台系统可以模块化成blog,博客后台系统可以模块化成admin,模块化便于对应用的管理扩展。
加载module的配置

//加载框架中自带gii模块和一个自定义admin模块  
'modules'=>array(  
    // uncomment the following to enable the Gii tool  
  
    'gii'=>array(  
        'class'=>'system.gii.GiiModule',  
        'password'=>'111111',  
        // If removed, Gii defaults to localhost only. Edit carefully to taste.  
        'ipFilters'=>array('127.0.0.1','::1'),  
    ),  
    'admin'   
      
),  

//应用初始化配置时通过CModule::setModules()来配置模块  
public function setModules($modules)  
{  
    foreach($modules as $id=>$module)  
    {  
        if(is_int($id))  
        {  
            $id=$module;  
            $module=array();  
        }  
        if(!isset($module['class']))  
        {  
            Yii::setPathOfAlias($id,$this->getModulePath().DIRECTORY_SEPARATOR.$id);  
            $module['class']=$id.'.'.ucfirst($id).'Module';  
        }  
  
        if(isset($this->_moduleConfig[$id]))  
            $this->_moduleConfig[$id]=CMap::mergeArray($this->_moduleConfig[$id],$module);  
        else  
            $this->_moduleConfig[$id]=$module;  
    }  
}  
定位模块
由module[/controller/action]获取路由中第一个"/"前字符串(必须是只含字母,否则抛出404错误)假定是模块id,根据模块id判断如果存在该id的模块或者存在该id的模块配置,则返回模块,由代码分析可以知道如果禁用一个模块很简单,只需在主配置文件中加上'enabled' => false就可。

CWebApplication:  
//路由分发,定位模块和模块下的controller  
public function createController($route,$owner=null)  
{  
     
    if($owner===null)  
        $owner=$this;  
    if(($route=trim($route,'/'))==='')  
        $route=$owner->defaultController;  
    $caseSensitive=$this->getUrlManager()->caseSensitive;  
  
    $route.='/';  
    while(($pos=strpos($route,'/'))!==false)  
    {  
        $id=substr($route,0,$pos);  
        if(!preg_match('/^\w+$/',$id))  
            return null;  
        if(!$caseSensitive)  
            $id=strtolower($id);  
        $route=(string)substr($route,$pos+1);  
        if(!isset($basePath))  // first segment  
        {  
            if(isset($owner->controllerMap[$id]))  
            {  
                return array(  
                    Yii::createComponent($owner->controllerMap[$id],$id,$owner===$this?null:$owner),  
                    $this->parseActionParams($route),  
                );  
            }  
             
            if(($module=$owner->getModule($id))!==null)  
                /* 
                    如果找到module,再次调用本方法, 
                    注意这个时候的第二个参数ower不再是CWebApplication或其子类,而是CWebModule子类 
                    这对获取控制器和视图的默认路径很重要,CWebModule控制器路径是相应module下面的 
                */  
                return $this->createController($route,$module);   
  
            $basePath=$owner->getControllerPath();  
            $controllerID='';  
        }  
        else  
            $controllerID.='/';  
        $className=ucfirst($id).'Controller';  
        $classFile=$basePath.DIRECTORY_SEPARATOR.$className.'.php';  
        if(is_file($classFile))  
        {  
            if(!class_exists($className,false))  
                require($classFile);  
            if(class_exists($className,false) && is_subclass_of($className,'CController'))  
            {  
                $id[0]=strtolower($id[0]);  
                return array(  
                    new $className($controllerID.$id,$owner===$this?null:$owner),  
                    $this->parseActionParams($route),  
                );  
            }  
            return null;  
        }  
        $controllerID.=$id;  
        $basePath.=DIRECTORY_SEPARATOR.$id;  
    }  
}  

CWebModule:  
/** 
 * Retrieves the named application module. 查找模块 
 * The module has to be declared in {@link modules}. A new instance will be created 
 * when calling this method with the given ID for the first time. 
 * @param string $id application module ID (case-sensitive) 
 * @return CModule the module instance, null if the module is disabled or does not exist. 
 */  
public function getModule($id)  
{  
    if(isset($this->_modules[$id]) || array_key_exists($id,$this->_modules))  
        return $this->_modules[$id];  
    else if(isset($this->_moduleConfig[$id]))  
    {  
        $config=$this->_moduleConfig[$id];  
        if(!isset($config['enabled']) || $config['enabled'])  
        {  
             
            Yii::trace("Loading \"$id\" module",'system.base.CModule');  
            $class=$config['class'];  
         
            unset($config['class'], $config['enabled']);  
            if($this===Yii::app())  
                $module=Yii::createComponent($class,$id,null,$config);  
            else  
                $module=Yii::createComponent($class,$this->getId().'/'.$id,$this,$config);  
            return $this->_modules[$id]=$module;  
        }  
    }  
}  
模块里有一个CWebModule的子类重载CWebModule的一些方法,通过int()导入模块中要导入的路径,通过 beforeControllerAction($controller, $action)和afterControllerAction($controller, $action)实现动作执行前后钩子的添加。

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.*',  
        ));  
    }  
  
    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;  
    }  
}