最新消息: 新版网站上线了!!!

YII框架分析笔记11:模块module

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)实现动作执行前后钩子的添加。
[php] view plaincopy
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;
}
}

转载请注明:谷谷点程序 » YII框架分析笔记11:模块module