可以是类名的字符串或是存储了类名和初始化参数的数组。
应用组件的配置存储在系统$config变量中(config/main.php里)的components项里:
// application components‘components’=>array( ‘log’=>array( ‘class’=>’CLogRouter’, ‘routes’=>array( array( ‘class’=>’CFileLogRoute’, ‘levels’=>’error, warning’, ), ), ), ‘user’=>array( // enable cookie-based authentication ‘allowAutoLogin’=>true, ),),
$config里的components项在CApplication的构造函数里被处理:
$this->configure($config);
configure()函数的处理很简单:
public function configure($config){ if(is_array($config)) { foreach($config as $key=>$value) $this->$key=$value; }}
$config里的每一项被当做属性传给$_app对象的setXXX()属性设置方法,其中’components’项在CWebApplication的CModule的父类setComponents()处理。
setComponents() 将’components’项里的类名及初始化参数存放到 $_componentConfig[]里:
public function setComponents($components){ // $config 里的’components’每一项 foreach($components as $id=>$component) { if($component instanceof IApplicationComponent) $this->setComponent($id,$component); // $_componentConfig里已经存在配置,合并$component else if(isset($this->_componentConfig[$id])) $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component); // 在$_componentConfig里新建项目 else $this->_componentConfig[$id]=$component; }}
CModule类重载了CComponent的__get()方法,优先访问应用组件对象。
public function __get($name){ if($this->hasComponent($name)) return $this->getComponent($name); else return parent::__get($name);}
hasComponent() 判断$_components[]中是否已存在组件实例,或$_componentConfig[]中存在组件配置信息。
public function hasComponent($id){ return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);}
getComponent() 判断组件实例已经存在于$_components[]中,则直接返回对象。
否则根据$_componentConfig[]里的组件配置数据调用 Yii::createComponent() 来创建组件,并将对象存入$_components[]中然后返回。
public function getComponent($id,$createIfNull=true){ if(isset($this->_components[$id])) return $this->_components[$id]; else if(isset($this->_componentConfig[$id]) && $createIfNull) { $config=$this->_componentConfig[$id]; unset($this->_componentConfig[$id]); if(!isset($config['enabled']) || $config['enabled']) { Yii::trace(“Loading ”$id” application component”,’system.web.CModule’); unset($config['enabled']); $component=Yii::createComponent($config); $component->init(); return $this->_components[$id]=$component; } }}
Yii::createComponent() 来完成应用组件的创建
public static function createComponent($config){ if(is_string($config)) { $type=$config; $config=array(); } else if(isset($config['class'])) { $type=$config['class']; unset($config['class']); } else throw new CException(Yii::t(‘yii’,'Object configuration must be an array containing a “class” element.’)); if(!class_exists($type,false)) $type=Yii::import($type,true); if(($n=func_num_args())>1) { $args=func_get_args(); if($n===2) $object=new $type($args[1]); else if($n===3) $object=new $type($args[1],$args[2]); else if($n===4) $object=new $type($args[1],$args[2],$args[3]); else { unset($args[0]); $class=new ReflectionClass($type); // Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+ // $object=$class->newInstanceArgs($args); $object=call_user_func_array(array($class,’newInstance’),$args); } } else $object=new $type; foreach($config as $key=>$value) $object->$key=$value; return $object;}