继续了解组件Component.php
1 /** 2 * Returns a value indicating whether a property is defined for this component. 3 * A property is defined if: 4 * 5 * - the class has a getter or setter method associated with the specified name 6 * (in this case, property name is case-insensitive); 7 * - the class has a member variable with the specified name (when `$checkVars` is true); 8 * - an attached behavior has a property of the given name (when `$checkBehaviors` is true). 9 * 与 Object 中的方法类似,只是添加了是否检测行为的参数 10 * @param string $name the property name 属性名 11 * @param boolean $checkVars whether to treat member variables as properties 12 * @param boolean $checkBehaviors whether to treat behaviors' properties as properties of this component 13 * 是否将行为属性作为该组件的属性来对待 14 * @return boolean whether the property is defined 属性是否定义 15 * @see canGetProperty() 可读 16 * @see canSetProperty() 可设置 17 */ 18 public function hasProperty($name, $checkVars = true, $checkBehaviors = true) 19 { // $checkVars 参数,用来检查对象是否具有该属性 (不是 getter 和 setter 定义出的属性) 20 //$checkBehaviors参数,用来设置是否检测behavior 21 return $this->canGetProperty($name, $checkVars, $checkBehaviors) || $this->canSetProperty($name, false, $checkBehaviors); 22 } 23 24 /** 25 * Returns a value indicating whether a property can be read. 26 * A property can be read if: 27 * 28 * - the class has a getter method associated with the specified name 29 * (in this case, property name is case-insensitive); 30 * - the class has a member variable with the specified name (when `$checkVars` is true); 31 * - an attached behavior has a readable property of the given name (when `$checkBehaviors` is true). 32 * 检查对象或类是否能够获取 $name 属性 33 * @param string $name the property name 属性名 34 * @param boolean $checkVars whether to treat member variables as properties 是否将成员对象作为属性 35 * @param boolean $checkBehaviors whether to treat behaviors' properties as properties of this component 36 * 是否将成员属性作为该组件的属性 37 * @return boolean whether the property can be read 属性是否可读 38 * @see canSetProperty() 39 */ 40 public function canGetProperty($name, $checkVars = true, $checkBehaviors = true) 41 { 42 if (method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name)) { 43 // 存在 'get' . $name方法 或 存在该属性, 返回true 44 return true; 45 } elseif ($checkBehaviors) { 46 $this->ensureBehaviors(); 47 foreach ($this->_behaviors as $behavior) { 48 // behavior 中存在名为 $name 的可读属性,认为该对象也存在 返回true 49 if ($behavior->canGetProperty($name, $checkVars)) { 50 return true; 51 } 52 } 53 } 54 return false; 55 } 56 57 /** 58 * Returns a value indicating whether a property can be set. 59 * A property can be written if: 60 * 61 * - the class has a setter method associated with the specified name 62 * (in this case, property name is case-insensitive); 63 * - the class has a member variable with the specified name (when `$checkVars` is true); 64 * - an attached behavior has a writable property of the given name (when `$checkBehaviors` is true). 65 * 检查对象或类是否能够设置 $name 属性 66 * @param string $name the property name 属性名 67 * @param boolean $checkVars whether to treat member variables as properties 是否将成员变量作为属性 68 * @param boolean $checkBehaviors whether to treat behaviors' properties as properties of this component 69 * 是否将行为属性作为该组件的属性 70 * @return boolean whether the property can be written 属性是否可写 71 * @see canGetProperty() 72 */ 73 public function canSetProperty($name, $checkVars = true, $checkBehaviors = true) 74 { 75 if (method_exists($this, 'set' . $name) || $checkVars && property_exists($this, $name)) { 76 // 存在 'set' . $name方法 或 存在该属性, 返回true 77 return true; 78 } elseif ($checkBehaviors) { 79 $this->ensureBehaviors(); 80 foreach ($this->_behaviors as $behavior) { 81 // behavior 中存在名为 $name 的可写属性,认为该对象也存在 返回true 82 if ($behavior->canSetProperty($name, $checkVars)) { 83 return true; 84 } 85 } 86 } 87 return false; 88 } 89 90 /** 91 * Returns a value indicating whether a method is defined. 92 * A method is defined if: 93 * 94 * - the class has a method with the specified name 95 * - an attached behavior has a method with the given name (when `$checkBehaviors` is true). 96 * 检查对象或类是否具有 $name 方法 97 * @param string $name the property name 98 * @param boolean $checkBehaviors whether to treat behaviors' methods as methods of this component 99 * @return boolean whether the property is defined 100 */ 101 public function hasMethod($name, $checkBehaviors = true) 102 { 103 if (method_exists($this, $name)) { 104 return true; 105 } elseif ($checkBehaviors) {//标记是否 check behavior 中的方法 106 $this->ensureBehaviors(); 107 foreach ($this->_behaviors as $behavior) { 108 // behavior 中存在名为 $name 的方法,就认为该方法也存在 109 if ($behavior->hasMethod($name)) { 110 return true; 111 } 112 } 113 } 114 return false; 115 } 116 117 /** 118 * Returns a list of behaviors that this component should behave as. 119 * 定义该对象中要用到的 behavior 120 * Child classes may override this method to specify the behaviors they want to behave as. 121 * 可重写 122 * The return value of this method should be an array of behavior objects or configurations 123 * indexed by behavior names. A behavior configuration can be either a string specifying 124 * the behavior class or an array of the following structure: 125 * 126 * ~~~ 127 * 'behaviorName' => [ 128 * 'class' => 'BehaviorClass', 129 * 'property1' => 'value1', 130 * 'property2' => 'value2', 131 * ] 132 * ~~~ 133 * 134 * Note that a behavior class must extend from [[Behavior]]. Behavior names can be strings 135 * or integers. If the former, they uniquely identify the behaviors. If the latter, the corresponding 136 * behaviors are anonymous and their properties and methods will NOT be made available via the component 137 * (however, the behaviors can still respond to the component's events). 138 * 行为名称可以是字符串或整数。如果是前者,他们是唯一确定的行为。如果是后者,相应的 139 * 行为是匿名的,它们的特性和方法将无法通过组件提供(仍然可以对组件的事件作出反应) 140 * Behaviors declared in this method will be attached to the component automatically (on demand). 141 * 在这种方法中声明的行为将自动连接到组件 142 * @return array the behavior configurations. 143 */ 144 public function behaviors() 145 { 146 return []; 147 } 148 149 /** 150 * Returns a value indicating whether there is any handler attached to the named event. 151 * 判断 _events 中的一个事件是否具有事件处理程序 152 * @param string $name the event name 事件名 153 * @return boolean whether there is any handler attached to the event. 154 */ 155 public function hasEventHandlers($name) 156 { 157 $this->ensureBehaviors(); 158 // 判断事件是否存在 $name 否则 调用Event类中的的方法判断是否有处理程序 159 return !empty($this->_events[$name]) || Event::hasHandlers($this, $name); 160 } 161 162 /** 163 * Attaches an event handler to an event. 164 * 处理程序的事件 165 * The event handler must be a valid PHP callback. The followings are 166 * 事件处理程序必须是有效的PHP回调函数,方便内置方法call_user_fucn()调用 167 * some examples: 168 * 169 * ~~~ 170 * function ($event) { ... } // anonymous function 171 * [$object, 'handleClick'] // $object->handleClick() 172 * ['Page', 'handleClick'] // Page::handleClick() 173 * 'handleClick' // global function handleClick() 174 * ~~~ 175 * 176 * The event handler must be defined with the following signature, 177 * 178 * ~~~ 179 * function ($event) 180 * ~~~ 181 * 182 * where `$event` is an [[Event]] object which includes parameters associated with the event. 183 * 184 * @param string $name the event name 事件名 185 * @param callable $handler the event handler 事件处理函数 186 * @param mixed $data the data to be passed to the event handler when the event is triggered. 187 * 当事件被触发时,将传递给事件处理程序的数据。 188 * When the event handler is invoked, this data can be accessed via [[Event::data]]. 189 * 当调用事件处理程序时,该数据可以通过 [[Event::data]] 访问 190 * @param boolean $append whether to append new event handler to the end of the existing 191 * handler list. If false, the new handler will be inserted at the beginning of the existing 192 * handler list. 193 * 是否将新事件处理程序附加到现有的处理程序列表的结尾。如果是错的,新的处理器将被插入在列表的开始的处理程序列表。 194 * @see off() 195 */ 196 public function on($name, $handler, $data = null, $append = true) 197 { 198 $this->ensureBehaviors(); 199 //$append 判断是否添加到事件(event)的后面,确保_events中有该事件 200 if ($append || empty($this->_events[$name])) { 201 //将事件处理程序和参数添加到event数组末尾 202 $this->_events[$name][] = [$handler, $data]; 203 } else { 204 //否则 添加到 event 的前面 205 array_unshift($this->_events[$name], [$handler, $data]); 206 } 207 } 208 209 /** 210 * Detaches an existing event handler from this component. 211 * This method is the opposite of [[on()]]. 212 * [[on()]]的反方法,用于删除事件处理程序 213 * @param string $name event name 事件名 214 * @param callable $handler the event handler to be removed. 事件处理程序 215 * If it is null, all handlers attached to the named event will be removed. 如果为空,清除所有的事件处理程序 216 * @return boolean if a handler is found and detached 是否发现并分离的处理程序 217 * @see on() 218 */ 219 public function off($name, $handler = null) 220 { 221 $this->ensureBehaviors(); 222 // 相应的事件不存在,返回false 223 if (empty($this->_events[$name])) { 224 return false; 225 } 226 //没有handler,清除该事件的所有事件处理程序 并返回true 227 if ($handler === null) { 228 unset($this->_events[$name]); 229 return true; 230 } else { 231 $removed = false;//删除标记 232 foreach ($this->_events[$name] as $i => $event) { 233 if ($event[0] === $handler) {//遍历该事件 判断事件处理程序是否符合 234 unset($this->_events[$name][$i]);//删除该事件处理程序 235 $removed = true; 236 } 237 } 238 if ($removed) { 239 // 如果删除成功,就需要重新构建以下索引,重新赋值 240 $this->_events[$name] = array_values($this->_events[$name]); 241 } 242 return $removed;//成功标记 243 } 244 } 245 246 /** 247 * Triggers an event. 触发事件 248 * This method represents the happening of an event. It invokes 249 * all attached handlers for the event including class-level handlers. 250 * @param string $name the event name 事件名 251 * @param Event $event the event parameter. If not set, a default [[Event]] object will be created. 252 * 事件参数. 如果未设置,默认的 [[Event]] 对象将被创建. 253 */ 254 public function trigger($name, Event $event = null) 255 { 256 //确保行为绑定 257 $this->ensureBehaviors(); 258 if (!empty($this->_events[$name])) { 259 // 事件名不为空 构建Event对象,为传入到handler函数中做准备 260 if ($event === null) { 261 $event = new Event; 262 } 263 if ($event->sender === null) { 264 $event->sender = $this; 265 } 266 $event->handled = false; 267 $event->name = $name; 268 foreach ($this->_events[$name] as $handler) { 269 // 遍历事件 给事件的data属性赋值 270 $event->data = $handler[1]; 271 // handler的函数中传入了一个Event对象 272 call_user_func($handler[0], $event); 273 // stop further handling if the event is handled 274 // 事件是否被处理,如果了处理事件即handled被设置为true时,停止进一步处理 275 if ($event->handled) { 276 return; 277 } 278 } 279 } 280 // invoke class-level attached handlers [[Event]] 的方法,触发类级别的事件处理程序 281 Event::trigger($this, $name, $event); 282 } 283 284 /** 285 * Returns the named behavior object.获取行为类 286 * @param string $name the behavior name 行为名 287 * @return Behavior the behavior object, or null if the behavior does not exist 行为对象,如果行为不存在为null 288 */ 289 public function getBehavior($name) 290 { 291 //确保行为绑定 292 $this->ensureBehaviors(); 293 //_behaviors中的行为类存在,返回行为类名,否则返回空 294 return isset($this->_behaviors[$name]) ? $this->_behaviors[$name] : null; 295 } 296 297 /** 298 * Returns all behaviors attached to this component. 获取所有的行为类 299 * @return Behavior[] list of behaviors attached to this component 300 */ 301 public function getBehaviors() 302 { 303 $this->ensureBehaviors(); //确保行为绑定 304 return $this->_behaviors; //直接返回所有行为 305 } 306 307 /** 308 * Attaches a behavior to this component. 309 * 内部使用的添加一个行为到该组件 310 * This method will create the behavior object based on the given 311 * configuration. After that, the behavior object will be attached to 312 * this component by calling the [[Behavior::attach()]] method. 313 * 通过提供的配置文件创建一个Behavior对象,通过调用 [[Behavior::attach()]] 方法添加行为到组件. 314 * @param string $name the name of the behavior. 行为名 315 * @param string|array|Behavior $behavior the behavior configuration. This can be one of the following: 316 * behavior配置 317 * - a [[Behavior]] object 一个[[Behavior]]类 318 * - a string specifying the behavior class 一个字符串形式的指定行为类 319 * - an object configuration array that will be passed to [[Yii::createObject()]] to create the behavior object. 320 * 一个配置文件数组,通过调用[[Yii::createObject()]] 创建一个行为对象. 321 * @return Behavior the behavior object 行为对象 322 * @see detachBehavior() 323 */ 324 public function attachBehavior($name, $behavior) 325 { 326 $this->ensureBehaviors();//确保行为绑定 327 return $this->attachBehaviorInternal($name, $behavior); //添加行为 328 } 329 330 /** 331 * Attaches a list of behaviors to the component. 添加行为列表到组件 332 * Each behavior is indexed by its name and should be a [[Behavior]] object, 333 * a string specifying the behavior class, or an configuration array for creating the behavior. 334 * 行为类通过行为名索引,且必须是一个 [[Behavior]] 对象指定的行为类或者一个配置数组 335 * @param array $behaviors list of behaviors to be attached to the component 行为列表 336 * @see attachBehavior() 337 */ 338 public function attachBehaviors($behaviors) 339 { 340 $this->ensureBehaviors();//确保行为绑定 341 foreach ($behaviors as $name => $behavior) { 342 //添加行为列表 343 $this->attachBehaviorInternal($name, $behavior); 344 } 345 } 346 347 /** 348 * Detaches a behavior from the component. 从组件解除行为 349 * The behavior's [[Behavior::detach()]] method will be invoked. 通过[[Behavior::detach()]]解除行为 350 * @param string $name the behavior's name. 行为名 351 * @return Behavior the detached behavior. Null if the behavior does not exist. 存在返回分离行为 不存在返回null 352 */ 353 public function detachBehavior($name) 354 { 355 $this->ensureBehaviors();//确保行为绑定 356 if (isset($this->_behaviors[$name])) { 357 //行为存在,解除行为 358 $behavior = $this->_behaviors[$name]; 359 unset($this->_behaviors[$name]); 360 //返回分离行为 361 $behavior->detach(); 362 return $behavior; 363 } else { 364 return null; 365 } 366 } 367 368 /** 369 * Detaches all behaviors from the component. 解除所有行为 370 */ 371 public function detachBehaviors() 372 { 373 $this->ensureBehaviors();//确保行为绑定 374 foreach ($this->_behaviors as $name => $behavior) { 375 //遍历解除行为 376 $this->detachBehavior($name); 377 } 378 } 379 380 /** 381 * Makes sure that the behaviors declared in [[behaviors()]] are attached to this component. 382 * 确保声明的行为都被添加到组件 383 */ 384 public function ensureBehaviors() 385 { 386 if ($this->_behaviors === null) { 387 $this->_behaviors = []; 388 foreach ($this->behaviors() as $name => $behavior) { 389 //遍历$this->behaviors()中的behaviors,并添加到$this->_behaviors数组中 390 $this->attachBehaviorInternal($name, $behavior); 391 } 392 } 393 } 394 395 /** 396 * Attaches a behavior to this component. 内部使用的为该对象添加behavior的方法 397 * @param string|integer $name the name of the behavior. If this is an integer, it means the behavior 398 * is an anonymous one. Otherwise, the behavior is a named one and any existing behavior with the same name 399 * will be detached first. 行为名. 如果是整数,说明该行为是匿名的 400 * @param string|array|Behavior $behavior the behavior to be attached 添加的行为 string|array|Behavior 401 * @return Behavior the attached behavior. 402 */ 403 private function attachBehaviorInternal($name, $behavior) 404 { 405 if (!($behavior instanceof Behavior)) { 406 // $behavior不是Behavior对象,认为是配置,则创建一个$behavior对象 407 $behavior = Yii::createObject($behavior); 408 } 409 if (is_int($name)) {//行为是整数,绑定到组件 410 $behavior->attach($this); 411 $this->_behaviors[] = $behavior; 412 } else { 413 if (isset($this->_behaviors[$name])) { 414 // 如果有同名的行为存在就先解绑掉 415 $this->_behaviors[$name]->detach(); 416 } 417 $behavior->attach($this);//重新绑定行为到组件 418 $this->_behaviors[$name] = $behavior; 419 } 420 return $behavior; 421 } 422 423