yii2框架随笔11

接下来我们来了解Component.php

目录为:vendor/yiisoft/yii2/base/Component.php

为了对Component.php有个初级的认识,我先截取一段yii2.0手册上的注释。

组件(Component)与对象(Object)

Yii 2.0 把 1.1 中的 CComponent 类拆分成了两个类:yii\base\Object 和 yii\base\Component。yii\base\Object 类是一个轻量级的基类,你可以通过 getters 和 setters 来定义对象的属性。yii\base\Component 类继承自 yii\base\Object,同时进一步支持 事件 和 行为

如果你不需要用到事件或行为,应该考虑使用 yii\base\Object 类作为基类。这种类通常用来表示基本的数据结构。

下面来看具体的代码。

<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */
namespace yii\base;
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);
        }
    }

 

posted @ 2016-04-21 23:49  TTKKK  阅读(227)  评论(0编辑  收藏  举报