接下来我们来了解Component.php
目录为:vendor/yiisoft/yii2/base/Component.php
为了对Component.php有个初级的认识,我先截取一段yii2.0手册上的注释。
组件(Component)与对象(Object)
Yii 2.0 把 1.1 中的 CComponent
类拆分成了两个类:yiiaseObject 和 yiiaseComponent。yiiaseObject 类是一个轻量级的基类,你可以通过 getters 和 setters 来定义对象的属性。yiiaseComponent 类继承自 yiiaseObject,同时进一步支持 事件 和 行为。
如果你不需要用到事件或行为,应该考虑使用 yiiaseObject 类作为基类。这种类通常用来表示基本的数据结构。
下面来看具体的代码。
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace yiibase; use Yii; /** * Component is the base class that implements the *property*, *event* and *behavior* features. *组件是Yii框架的基类,实现了属性,事件,行为三种功能。 * Component provides the *event* and *behavior* features, in addition to the *property* feature which is implemented in * its parent class [[Object]]. * 组件提供事件行为,通过附加到父类[Object]属性执行中。 * Event is a way to "inject" custom code into existing code at certain places. For example, a comment object can trigger * an "add" event when the user adds a comment. We can write custom code and attach it to this event so that when the event * is triggered (i.e. comment will be added), our custom code will be executed. * 事件是一种在特定的地方“注入”自定义代码到现有的代码。例如一个评论对象能够在用户添加评论的时候触发一个add事件,我们能够自定义一些代码添加到 这个事件中,在添加评论的时候会触发事件,执行自定义的代码, * An event is identified by a name that should be unique within the class it is defined at. Event names are *case-sensitive*. * 事件的名称在类中的定义是唯一的,事件的名称区分大小写。 * One or multiple PHP callbacks, called *event handlers*, can be attached to an event. * 一个或多个PHP回调,叫*event handlers *,事件处理程序可以被附加到一个事件 * You can call [[trigger()]] to * raise an event. When an event is raised, the event handlers will be invoked automatically in the order they were * attached. * 你可以通过调用[[trigger()]]触发事件,事件处理程序将会按照添加的先后顺序依次执行 * To attach an event handler to an event, call [[on()]]: * ~~~添加事件是通过on()方法添加 * $post->on('update', function ($event) { * // 给update方法添加一个匿名函数事件,该事件的作用是发送邮件信息。 * }); * ~~~ * * In the above, an anonymous function is attached to the "update" event of the post. You may attach * the following types of event handlers: * 在上面,一个匿名函数附加到事件“update”。你可以连接以下类型的事件处理程序: * * * - anonymous function: `function ($event) { ... }` 匿名函数 * - object method: `[$object, 'handleAdd']` 对象的方法 以数组的方式传入 * - static class method: `['Page', 'handleAdd']` 静态方法 以数组的方式传入 * - global function: `'handleAdd'` 全局函数 * class Component extends Object { /** * 用来存储该对象的 event * @var array the attached event handlers (event name => handlers) */ private $_events = []; /** * 用来存储该对象的 behavior * @var Behavior[]|null the attached behaviors (behavior name => behavior). This is `null` when not initialized. */ private $_behaviors; /** * Returns the value of a component property. * This method will check in the following order and act accordingly: * * - a property defined by a getter: return the getter result * - a property of a behavior: return the behavior property value * * Do not call this method directly as it is a PHP magic method that * will be implicitly called when executing `$value = $component->property;`. * 返回一个组件的属性值。 *这个方法将检查以下顺序并采取相应的行动: * * - 通过一个getter定义的属性:返回getter的结果 * - 一个行为的属性:返回的行为属性值 * *不要直接调用此方法,因为它是一个PHP魔术方法 *将执行` * * 重写 Object 中的 getter 方法,添加对 behaviors 的处理,循环 behaviors,如果其中有相应的方法,就执行它 * * @param string $name the property name * @return mixed the property value or the value of a behavior's property * @throws UnknownPropertyException if the property is not defined * @throws InvalidCallException if the property is write-only. * @see __set() */ public function __get($name) { $getter = 'get' . $name; if (method_exists($this, $getter)) { // read property, e.g. getName() // $getter 方法存在的话就直接调用方法 return $this->$getter(); } else { // behavior property $this->ensureBehaviors(); foreach ($this->_behaviors as $behavior) { if ($behavior->canGetProperty($name)) { // 如果 behavior 中含有该属性,就返回 behavior 中的这个属性 return $behavior->$name; } } } if (method_exists($this, 'set' . $name)) {//跟父类相同,判断属性是否只写 throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name); } else { throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);//如果没被调用,抛出异常信息:属性不明。 } } /** * Sets the value of a component property. * This method will check in the following order and act accordingly: * * - a property defined by a setter: set the property value * - an event in the format of "on xyz": attach the handler to the event "xyz" * - a behavior in the format of "as xyz": attach the behavior named as "xyz" * - a property of a behavior: set the behavior property value * * Do not call this method directly as it is a PHP magic method that * will be implicitly called when executing `$component->property = $value;`. * * 重写 Object 中的 setter 方法 * 如果 $name 是 'on xyz',就会将 xyz 事件添加到该对象中 * 如果 $name 是 'as xyz',就会将 xyz 行为添加到该对象中 * 添加对 behaviors 的处理,循环 behaviors,如果其中有相应的属性,就设置它 * * @param string $name the property name or the event name * @param mixed $value the property value * @throws UnknownPropertyException if the property is not defined * @throws InvalidCallException if the property is read-only. * @see __get() */ public function __set($name, $value) { $setter = 'set' . $name; if (method_exists($this, $setter)) { // set property // 存在 $setter 方法,其优先级最高 $this->$setter($value); return; } elseif (strncmp($name, 'on ', 3) === 0) { // 如果 $name 是以 'on ' 开头的,就添加事件 // on event: attach event handler $this->on(trim(substr($name, 3)), $value); return; } elseif (strncmp($name, 'as ', 3) === 0) { // 如果 $name 是以 'as ' 开头的,添加行为 // as behavior: attach behavior $name = trim(substr($name, 3)); // $value 是一个 behavior 的实例或者 behavior 的配置 $this->attachBehavior($name, $value instanceof Behavior ? $value : Yii::createObject($value)); return; } else { // behavior property $this->ensureBehaviors(); // 循环所有的 behavior foreach ($this->_behaviors as $behavior) { if ($behavior->canSetProperty($name)) { // 如果 behavior 中有 $name 属性,就将 $value 赋给它 $behavior->$name = $value; return; } } } if (method_exists($this, 'get' . $name)) {//抛出异常 throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name); } else { throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name); } }