标签:
前面阅读了Yii2的两个基本类Object和Component,了解了Yii的三个重要概念属性、事件、行为,下面开始阅读Event类,Event类是所有事件类的基类:
1 <?php 2 /** 3 * @link http://www.yiiframework.com/ 4 * @copyright Copyright (c) 2008 Yii Software LLC 5 * @license http://www.yiiframework.com/license/ 6 */ 7 8 namespace yii\base; 9 10 /** 11 * Event is the base class for all event classes. 12 * Event 是所有事件类的基类,是对Component的深化 13 * 14 * It encapsulates the parameters associated with an event. 15 * The [[sender]] property describes who raises the event. 16 * And the [[handled]] property indicates if the event is handled. 17 * If an event handler sets [[handled]] to be true, the rest of the 18 * uninvoked handlers will no longer be called to handle the event. 19 * 20 * Additionally, when attaching an event handler, extra data may be passed 21 * and be available via the [[data]] property when the event handler is invoked. 22 * 23 * @author Qiang Xue <qiang.xue@gmail.com> 24 * @since 2.0 25 */ 26 class Event extends Object 27 { 28 /** 29 * @var string the event name. This property is set by [[Component::trigger()]] and [[trigger()]]. 30 * Event handlers may use this property to check what event it is handling. 31 * 事件的名字,通过[[Component::trigger()]] 和 [[trigger()]]方法设置,事件处理程序通过这个属性类检查处理的事件 32 */ 33 public $name; 34 /** 35 * @var object the sender of this event. If not set, this property will be 36 * set as the object whose "trigger()" method is called. 37 * This property may also be a `null` when this event is a 38 * class-level event which is triggered in a static context. 39 * 40 * 触发事件的对象,如果未设置,则设置为调用"trigger()"方法的对象,如果是在静态环境下触发的类级别的事件,怎为空 41 */ 42 public $sender; 43 /** 44 * @var boolean whether the event is handled. Defaults to false. 45 * When a handler sets this to be true, the event processing will stop and 46 * ignore the rest of the uninvoked event handlers. 47 * 48 * 记录事件是否已被处理,当 handled 被设置为 true 时,执行到这个 event 的时候,会停止,并忽略剩下的 event 49 */ 50 public $handled = false; 51 /** 52 * @var mixed the data that is passed to [[Component::on()]] when attaching an event handler. 53 * Note that this varies according to which event handler is currently executing. 54 * 事件加载时传入的数据,对应当前执行的事件处理程序 55 */ 56 public $data; 57 58 /** 59 * @var array contains all globally registered event handlers. 60 * 存储所有的 event,因为是 static 的属性,所有的 event 对象/类都共享这一份数据 61 */ 62 private static $_events = []; 63 64 65 /** 66 * Attaches an event handler to a class-level event. 67 * 为一个类添加事件 68 * 69 * When a class-level event is triggered, event handlers attached 70 * to that class and all parent classes will be invoked. 71 * 72 * For example, the following code attaches an event handler to `ActiveRecord`‘s 73 * `afterInsert` event: 74 * 75 * ```php 76 * Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) { 77 * Yii::trace(get_class($event->sender) . ‘ is inserted.‘); 78 * }); 79 * ``` 80 * 81 * The handler will be invoked for EVERY successful ActiveRecord insertion. 82 * 83 * For more details about how to declare an event handler, please refer to [[Component::on()]]. 84 * 85 * @param string|object $class 定义的类级别的对象或者类名称. 86 * @param string $name 事件名 87 * @param callable $handler 事件处理程序. 88 * @param mixed $data 数据. 89 * When the event handler is invoked, this data can be accessed via [[Event::data]]. 90 * @param boolean $append whether to append new event handler to the end of the existing 91 * handler list. If false, the new handler will be inserted at the beginning of the existing 92 * handler list. 93 * @see off() 94 */ 95 public static function on($class, $name, $handler, $data = null, $append = true) 96 { 97 // 去掉 class 最左边的斜线 98 $class = ltrim($class, ‘\\‘); 99 if ($append || empty(self::$_events[$name][$class])) { 100 // 如果 append 为true,就放到 $_events 中名字为 $name 的数组的最后 101 self::$_events[$name][$class][] = [$handler, $data]; 102 } else { 103 //否则放到最前面 104 array_unshift(self::$_events[$name][$class], [$handler, $data]); 105 } 106 } 107 108 /** 109 * Detaches an event handler from a class-level event. 110 * [[on()]]方法的反方法,移除一个类的事件 111 * This method is the opposite of [[on()]]. 112 * 113 * @param string|object $class 定义的类级别的对象或者类名称. 114 * @param string $name 事件名 115 * @param callable $handler 事件处理程序. 116 * If it is null, all handlers attached to the named event will be removed. 117 * @return boolean whether a handler is found and detached. 118 * @see on() 119 */ 120 public static function off($class, $name, $handler = null) 121 { 122 // 去掉 class 最左边的斜线 123 $class = ltrim($class, ‘\\‘); 124 if (empty(self::$_events[$name][$class])) { 125 // 如果不存在该事件,返回false 126 return false; 127 } 128 if ($handler === null) { 129 // 如果 handler 为空,也就是没有规定移除的事件处理程序,直接将该事件移除,即移出所有的是这个名字的事件 130 unset(self::$_events[$name][$class]); 131 return true; 132 } else { 133 $removed = false; //移除标记 134 // 如果 $handler 不为空,遍历 $_events 找到相应的 handler,只移除这个 handler 和 data 组成的数组 135 foreach (self::$_events[$name][$class] as $i => $event) { 136 if ($event[0] === $handler) { 137 unset(self::$_events[$name][$class][$i]); 138 $removed = true; 139 } 140 } 141 if ($removed) { 142 //如果删除成功,调用array_values方法重新赋值,初始化索引 143 self::$_events[$name][$class] = array_values(self::$_events[$name][$class]); 144 } 145 146 return $removed; 147 } 148 } 149 150 /** 151 * Returns a value indicating whether there is any handler attached to the specified class-level event. 152 * Note that this method will also check all parent classes to see if there is any handler attached 153 * to the named event. 154 * 检测在某个类或者对象是否具有某个事件/会同时检测父类 155 * 156 * @param string|object $class 定义的类级别的对象或者类名称. 157 * @param string $name 事件名 158 * @return boolean whether there is any handler attached to the event. 159 */ 160 public static function hasHandlers($class, $name) 161 { 162 if (empty(self::$_events[$name])) { 163 //如果不存在,直接返回false 164 return false; 165 } 166 if (is_object($class)) { 167 // 如果是一个 object,就获取其类名 get_class 内置函数,用于获取对象的方法 168 $class = get_class($class); 169 } else { 170 // 如果是一个类名,就去掉 class 最左边的斜杠 171 $class = ltrim($class, ‘\\‘); 172 } 173 //将该类/该对象对应的类的父类以及该类/该对象对应的类实现的接口名称合并到一个数组中 174 $classes = array_merge( 175 [$class], 176 class_parents($class, true),//获取父类的类名 177 class_implements($class, true)//获取当前类和父类实现的所有接口类名 178 ); 179 //判断是否存在事件处理程序,存在返回true 180 foreach ($classes as $class) { 181 if (!empty(self::$_events[$name][$class])) { 182 return true; 183 } 184 } 185 186 return false; 187 } 188 189 /** 190 * Triggers a class-level event. 191 * This method will cause invocation of event handlers that are attached to the named event 192 * for the specified class and all its parent classes. 193 * 触发某个类或者对象的某个事件/会同时作用于父类 194 * 195 * @param string|object $class 定义的类级别的对象或者类名称. 196 * @param string $name 事件名 197 * @param Event $event the event parameter. If not set, a default [[Event]] object will be created. 198 */ 199 public static function trigger($class, $name, $event = null) 200 { 201 if (empty(self::$_events[$name])) { 202 //如果事件不存在,直接返回 203 return; 204 } 205 if ($event === null) { 206 // 构建Event对象,为传入到handler函数中做准备 207 $event = new static; 208 } 209 $event->handled = false;//事件是否被处理标志 210 $event->name = $name;//事件名 211 212 if (is_object($class)) { 213 if ($event->sender === null) { 214 // 如果 $class 是个对象,并且是 sender 为空,就将 $class 赋给 sender,即 $class 就是触发事件的对象 215 $event->sender = $class; 216 } 217 $class = get_class($class);//取得类名称 218 } else { 219 $class = ltrim($class, ‘\\‘);//去掉类名称左边的斜线 220 } 221 //将该类/该对象对应的类的父类以及该类/该对象对应的类实现的接口名称合并到一个数组中 222 $classes = array_merge( 223 [$class], 224 class_parents($class, true), 225 class_implements($class, true) 226 ); 227 228 foreach ($classes as $class) {//遍历所有的类 229 if (!empty(self::$_events[$name][$class])) {//找到符合条件的类 230 foreach (self::$_events[$name][$class] as $handler) { 231 $event->data = $handler[1];//设置data数据 232 call_user_func($handler[0], $event);//调用处理程序 233 if ($event->handled) {//事件是否被处理标志为真,结束执行 234 return; 235 } 236 } 237 } 238 } 239 } 240 }
标签:
原文地址:http://www.cnblogs.com/isleep/p/5400051.html