yii框架源码分析之CComponent

  
    
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:
* <pre>
* array(
* 'class'=>'path.to.BehaviorClass',
* 'property1'=>'value1',
* 'property2'=>'value2',
* )
* </pre>
* @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 )));
}
}

你可能感兴趣的:(component)