首页 > PHP资讯 > PHP培训技术 > Yii框架分析(二)——CComponent类剖析

Yii框架分析(二)——CComponent类剖析

PHP培训技术

)。

行为类必须实现 IBehavior 接口,大多数行为可以从 CBehavior 基类扩展而来。

IBehavior接口提供了4个方法。
attach($component)将自身关联到组件,detach($component) 解除$component关联,getEnabled()和setEnabled()设置行为对象的有效性。

行为对象存放在组件的$_m[]数组里,数组键值为行为名字符串,数组值为行为类对象。

组件通过attachBehavior ($name,$behavior)来扩展一个行为:
$component-> attachBehavior (‘render’,$htmlRender)
为$component添加了一个名字为render的行为,$htmlRender 需是一个实现 IBehavior 接口的对象,或是一个数组:

array( ‘class’=>’path.to.BehaviorClass’,    ‘property1′=>’value1′,    ‘property2′=>’value2′,* )

会根据数组的class来创建行为对象并设置属性值。

$htmlRender被存储到$_m[‘render’]中。

外部调用一个组件未定义的方法时,魔术方法__call()?会遍历所有行为对象,如果找到同名方法就调用之。

例如?$htmlRender?有个方法?renderFromFile(),则可以直接当做组件的方法来访问:

$component-> renderFromFile ()

4.CComponent源码分析

//所有部件的基类class CComponent{    private $_e;    private $_m;    //获取部件属性、事件和行为的magic method    public function __get($name)    {        $getter=’get’.$name;        //是否存在属性的get方法        if(method_exists($this,$getter))            return $this->$getter();        //以on开头,获取事件处理句柄        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))        {            // 事件名小写            $name=strtolower($name);            // 如果_e[$name] 不存在,返回一个空的CList事件句柄队列对象            if(!isset($this->_e[$name]))                $this->_e[$name]=new CList;            // 返回_e[$name]里存放的句柄队列对象            return $this->_e[$name];        }        // _m[$name] 里存放着行为对象则返回        else if(isset($this->_m[$name]))            return $this->_m[$name];        else            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is not defined.’,                array(‘{class}’=>get_class($this), ‘{property}’=>$name)));    }    /**    * PHP magic method    * 设置组件的属性和事件    */     public function __set($name,$value)    {        $setter=’set’.$name;        //是否存在属性的set方法        if(method_exists($this,$setter))            $this->$setter($value);        //name以on开头,这是事件处理句柄        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))        {            // 事件名小写            $name=strtolower($name);            // _e[$name] 不存在则创建一个CList对象            if(!isset($this->_e[$name]))                $this->_e[$name]=new CList;            // 添加事件处理句柄            $this->_e[$name]->add($value);        }        // 属性没有set方法,只有get方法,为只读属性,抛出异常        else if(method_exists($this,’get’.$name))            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is read only.’,                array(‘{class}’=>get_class($this), ‘{property}’=>$name)));        else            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is not defined.’,                array(‘{class}’=>get_class($this), ‘{property}’=>$name)));    }    /**    * PHP magic method    * 为isset()函数提供是否存在属性和事件处理句柄的判断    */    public function __isset($name)    {        $getter=’get’.$name;        if(method_exists($this,$getter))            return $this->$getter()!==null;        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))        {            $name=strtolower($name);            return isset($this->_e[$name]) && $this->_e[$name]->getCount();        }        else            return false;    }    /**    * PHP magic method    * 设置属性值为空或删除事件名字对应的处理句柄    */    public function __unset($name)    {        $setter=’set’.$name;        if(method_exists($this,$setter))            $this->$setter(null);        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))            unset($this->_e[strtolower($name)]);        else if(method_exists($this,’get’.$name))            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is read only.’,        array(‘{class}’=>get_class($this), ‘{property}’=>$name)));    }    /**    * PHP magic method    *?CComponent未定义的类方法,寻找行为类里的同名方法,实现行为方法的调用    */    public function __call($name,$parameters)    {        // 行为类存放的$_m数组不空        if($this->_m!==null)        {            // 循环取出$_m数组里存放的行为类            foreach($this->_m as $object)            {                // 行为类对象有效,并且方法存在,调用之                if($object->enabled && method_exists($object,$name))                    return call_user_func_array(array($object,$name),$parameters);            }        }        throw new CException(Yii::t(‘yii’,'{class} does not have a method named “{name}”.’,            array(‘{class}’=>get_class($this), ‘{name}’=>$name)));    }    /**    * 根据行为名返回行为类对象    */    public function asa($behavior)    {        return isset($this->_m[$behavior]) ? $this->_m[$behavior] : null;    }    /**    * Attaches a list of behaviors to the component.    * Each behavior is indexed by its name and should be an instance of    *?{@link?IBehavior}, a string specifying the behavior class, or an    * array of the following structure:    * 
    * array(    *???? ‘class’=>’path.to.BehaviorClass’,    *???? ‘property1′=>’value1′,    *???? ‘property2′=>’value2′,    * )    * 
* @param array list of behaviors to be attached to the component * @since 1.0.2 */ public function attachBehaviors($behaviors) { // $behaviors为数组 $name=>$behavior foreach($behaviors as $name=>$behavior) $this->attachBehavior($name,$behavior); } /** * 添加一个行为到组件 */ public function attachBehavior($name,$behavior) { /* $behavior不是IBehavior接口的实例,则为 * array( *???? ‘class’=>’path.to.BehaviorClass’, *???? ‘property1′=>’value1′, *???? ‘property2′=>’value2′, * ) * 传递给Yii::createComponent创建行为了并初始化对象属性 */ if(!($behavior instanceof IBehavior)) $behavior=Yii::createComponent($behavior); $behavior->setEnabled(true); $behavior->attach($this); return $this->_m[$name]=$behavior; } /** * Raises an event. * This method represents the happening of an event. It invokes * all attached handlers for the event. * @param string the event name * @param CEvent the event parameter * @throws CException if the event is undefined or an event handler is invalid. */ public function raiseEvent($name,$event) { $name=strtolower($name); // _e[$name] 事件处理句柄队列存在 if(isset($this->_e[$name])) { // 循环取出事件处理句柄 foreach($this->_e[$name] as $handler) { // 事件处理句柄为全局函数 if(is_string($handler)) call_user_func($handler,$event); else if(is_callable($handler,true)) { // an array: 0 – object, 1 – method name list($object,$method)=$handler; if(is_string($object))?// 静态类方法 call_user_func($handler,$event); else if(method_exists($object,$method)) $object->$method($event); else throw new CException(Yii::t(‘yii’,'Event “{class}.{event}” is attached with an invalid handler “{handler}”.’,array(‘{class}’=>get_class($this), ‘{event}’=>$name, ‘{handler}’=>$handler[1]))); } else throw new CException(Yii::t(‘yii’,'Event “{class}.{event}” is attached with an invalid handler “{handler}”.’,array(‘{class}’=>get_class($this), ‘{event}’=>$name, ‘{handler}’=>gettype($handler)))); // $event 的handled 设置为true后停止队列里剩余句柄的调用 if(($event instanceof CEvent) && $event->handled) return; } } else if(YII_DEBUG && !$this->hasEvent($name)) throw new CException(Yii::t(‘yii’,'Event “{class}.{event}” is not defined.’, array(‘{class}’=>get_class($this), ‘{event}’=>$name))); }}

PHP培训技术

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持19不支持0