Yii Event的理解

来源:互联网 发布:淘宝商城医药 编辑:程序博客网 时间:2024/05/21 22:27

参考自http://www.cnblogs.com/JosephLiu/archive/2011/12/12/2285078.html

加上了个人理解和一点补充

Event可分为Event和EventHandler

Event说明某件事发生了,EventHandler说明如何处理发生的事

在Yii中Event一般是在CComponet的子类中扩展出来的,一般以on开头。

1 public function onClick($event)2 {3     $this->raiseEvent('onClick',$event);4 }
例如上面的代码,他就代表一个Event。

要附加一个事件处理程序,参见attachEventHandler。你也可以使用如下语法:

$component->onClick=$callback;    // or $component->onClick->add($callback);,$component应该为CComponent的子类的实例
$component->onClick=$callback;//这个是通过CComponent的__set函数为事件onClick添加了事件处理函数(EventHandler)
public function __set($name,$value)
{
    
$setter='set'.$name;
    if(
method_exists($this,$setter))
        return 
$this->$setter($value);//这里是CComponent的setter方法
    else if(
strncasecmp($name,'on',2)===&& method_exists($this,$name))//为事件onXXX添加
EventHandler
    {
        
// duplicating getEventHandlers() here for performance
        
$name=strtolower($name);
        if(!isset(
$this->_e[$name]))//先检查是否已经存在onXXX这个Event
            
$this->_e[$name]=new CList;//如果没有,新建一个对应Event的EventHandler列表
        return 
$this->_e[$name]->add($value);//CList中的add(),为事件添加EventHandler
    }
    else if(
is_array($this->_m))//这里是行为的部分
    {
        foreach(
$this->_m as $object)
        {
            if(
$object->getEnabled() && (property_exists($object,$name) || $object->canSetProperty($name)))
                return 
$object->$name=$value;
        }
    }
    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)));
}

那么,当我们去调用publicfunction onClick($event)这个函数时,就表明一个事件发生了,通过raiseEvent('onXXX',$event)触发

foreach语句中逐一执行Event的EventHandler,有些是可控制执行到那个EventHandler就停止的,如:

CEvent是所有事件类的基类。
它封装了与事件相关的参数。 sender属性指的是谁发起来的事件。handled属性指的是事件的处理方式. 如果一个事件处理程序设置了handled为true,其它未处理的事件处理程序将不会被调用。

其中EventHandler是PHP的标准回调函数,有以下几种情况,是给call_user_func调用的

1、array('ClassName',  'staticMethodName') .

2、array($object, 'objectMethod').

3、$component->attachEventHandler('onClick',  create_function('$event', 'echo "Click!";'));

4、Since PHP 5.3, you can use anonymous functions without create_function:
$component->attachEventHandler('onClick', function($event){
    echo "Click!";
});

public function raiseEvent($name,$event)
{
    
$name=strtolower($name);
    if(isset(
$this->_e[$name]))//判断这个Event是否存在
    {
        foreach(
$this->_e[$name] as $handler)

        {
            if(
is_string($handler))
                
call_user_func($handler,$event);
            else if(
is_callable($handler,true))
            {
                if(
is_array($handler))
                {
                    
// an array: 0 - object, 1 - method name
                    
list($object,$method)=$handler;
                    if(
is_string($object))    // static method call
                        
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 
// PHP 5.3: anonymous function:PHP 5.3的匿名函数特性
                    
call_user_func($handler,$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}'=>gettype($handler))));
            
// stop further handling if param.handled is set 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)));
}

以上就完成了一个事件发生和处理。一种典型的例子:

在组件里定义Event是CComponent的子类,在model里定义onXXX()函数,在控制器里为Event添加EventHandler

原创粉丝点击