Yii框架组件的事件机制原理与用法分析
本文实例讲述了Yii框架组件的事件机制原理与用法。分享给大家供大家参考,具体如下
在深入分析 Yii 的运行之前,我们先来看一下 Yii 框架中一个很重要的机制 - 事件。
Yii 官方参考文档关于组件事件的解释
=======================================================================
组件事件是一些特殊的属性,它们使用一些称作 事件句柄 ( event handlers )的方法作为其值。 附加 ( 分配 ) 一个方法到一个事件将会引起方法在事件被唤起处自动被调用。, 一个组件的行为可能会被一种在部件开发过程中不可预见的方式修改。
组件事件以 on 开头的命名方式定义。和属性通过 getter/setter 方法来定义的命名方式一样, 事件的名称是大小写不敏感的。以下代码定义了一个 onClicked 事件 :
public function onClicked($event) { $this->raiseEvent('onClicked', $event); }
这里作为事件参数的 $event 是 或其子类的实例。
我们可以附加一个方法到此 event ,如下所示 :
$ponent->onClicked=$callback;
这里的 $callback 指向了一个有效的 PHP 回调。它可以是一个全局函数也可以是类中的一个方法。 如果是后者,它必须以一个数组的方式提供 : array($object,'methodName').
事件句柄的结构如下
function methodName($event) { ...... }
这里的 $event 即描述事件的参数(它来源于 raiseEvent() 调用)。 $event 参数是 或其子类的实例。 至少,它包含了关于谁触发了此事件的信息。
从版本 1.0.10 开始,事件句柄也可以是一个 PHP 5.3 以后支持的匿名函数。例如,
$ponent->onClicked=function($event) { ...... }
如果我们现在调用 onClicked() , onClicked 事件将被触发(在 onClicked() 中), 附属的事件句柄将被自动调用。
一个事件可以绑定多个句柄。当事件触发时, 这些句柄将被按照它们绑定到事件时的顺序依次执行。如果句柄决定组织后续句柄被执行,它可以设置 为 true 。
=======================================================================
从这一句开始”我们可以附加一个方法到此 event “,读者可能 就不知道是什么意思了,于是看一下 CComponent 的源码
/ 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); //先查看成员变量是否有以此命名的事件 if(isset($this->_e[$name])) { //如果有,这个成员保存的是每一个事件处理器 //以数组的方式保存 foreach($this->_e[$name] as $handler) { //如果事件处理器是一个字符串,那么就是一个全局函数 if(is_string($handler)) call_user_func($handler,$event); //如果不是,那么有可能是一个数组,该数组包含一个对象和方法名 //参考http://php./manual/en/function.is-callable.php else if(is_callable($handler,true)) { // 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 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)))); // s further handling if param.handled is set true //如果想停止继续循环获取事件的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))); //如果_e中没有这个成员也没关系 }
我们再看一下 CEvent 的代码( CComponent.php )
class CEvent extends CComponent { / @var object the sender of this event / public $sender; / @var boolean whether the event is handled. Defaults to false. When a handler sets this true, the rest uninvoked handlers will not be invoked anymore. / public $handled=false; / Constructor. @param mixed sender of the event / public function __construct($sender=null) { $this->sender=$sender; } }
CEvent 只包含两个变量 $sender 记录事件触发者, $handled 表示事件是否已经被“解决”。
接着我们再看一下如何给一个组件注册一个事件处理器
/ Attaches an event handler to an event. An event handler must be a valid PHP callback, i.e., a string referring to a global function name, or an array containing two elements with the first element being an object and the second element a method name of the object. An event handler must be defined with the following signature, <pre> function handlerName($event) {} </pre> where $event includes parameters associated with the event. This is a convenient method of attaching a handler to an event. It is equivalent to the following code: <pre> $ponent->getEventHandlers($eventName)->add($eventHandler); </pre> Using {@link getEventHandlers}, one can also specify the excution order of multiple handlers attaching to the same event. For example: <pre> $ponent->getEventHandlers($eventName)->insertAt(0,$eventHandler); </pre> makes the handler to be invoked first. @param string the event name @param callback the event handler @throws CException if the event is not defined @see detachEventHandler / public function attachEventHandler($name,$handler) { $this->getEventHandlers($name)->add($handler); } / Returns the list of attached event handlers for an event. @param string the event name @return CList list of attached event handlers for the event @throws CException if the event is not defined / public function getEventHandlers($name) { if($this->hasEvent($name)) { $name=strtolower($name); if(!isset($this->_e[$name])) //新建一个CList保存事件的处理器 $this->_e[$name]=new CList; return $this->_e[$name]; } else throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.', array('{class}'=>get_class($this), '{event}'=>$name))); }
由此可以看出,获取事件处理器对象,如果没有则使用 CList ( Yii 实现的一个链表)创建,然后将事件处理器 add 进这个对象中,这样就可以在 raiseEvent 时遍历所有的事件处理器进行处理了,有点儿类似 jQuery 中注册了多个 click 事件处理器之后,当 click 事件触发时,会按顺序调用之前注册的事件处理器。
更多关于Yii相关内容感兴趣的读者可查看本站专题《》、《》、《》、《》、《》、《》及《》
希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程