十一、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(1)

关联阅读 

十一、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(1)

十二、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(2)

十三、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(3)

十四、逐行阅读Yii2.0.43源码_Yii框架文件Component.php(4)
 

目录

一.、3个属性

 二、6个魔术方法


        Container类继承Component类, Component类继承BaseObject类,Component类实现*property*,*event*,*behavior*特性的基类

一.、3个属性

1.$_events 事件数组

2.$_eventWildcards 通配符事件数组

3.$_behaviors 行为数组

    /**
     * 事件处理函数数组
     * 格式 [event name => handlers]
     */
    private $_events = [];


    /**
     * 通配符事件处理函数数组
     * 格式 [event name wildcard => handlers]
     */
    private $_eventWildcards = [];


    /**
     * 行为数组,默认为 null
     * 格式 [behavior name => behavior]
     */
    private $_behaviors;

 二、6个魔术方法

1.__get魔术方法,返回组件属性值,执行逻辑分为以下四步:

  • 第一步:是否有getXXX方法,有则调用获取结果返回;
  • 第二步:遍历行为数组,查找XXX属性,有则返回;
  • 第三步:是否有setXXX方法,有则抛出InvalidCallException异常
  • 第四步:以上三步均未得到执行,抛出UnknownPropertyException异常
    /**
     * 返回组件属性值
     * 主要分为四步执行:XXX属性名称
     * 第一步:是否有getXXX方法,有则调用获取结果返回;
     * 第二步:遍历行为数组,查找XXX属性,有则返回;
     * 第三步:是否有setXXX方法,有则抛出InvalidCallException异常
     * 第四步:以上三步均未得到执行,抛出UnknownPropertyException异常
     */
    public function __get($name)
    {
        $getter = 'get' . $name;
        if (method_exists($this, $getter)) {
            // read property, e.g. getName()
            return $this->$getter();
        }

        // behavior property
        $this->ensureBehaviors();
        foreach ($this->_behaviors as $behavior) {
            if ($behavior->canGetProperty($name)) {
                return $behavior->$name;
            }
        }

        if (method_exists($this, 'set' . $name)) {
            throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);
        }

        throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
    }

2.__set魔术方法,设置组件属性,执行逻辑分为以下六步:

  • 第一步:是否有setXXX方法,有则调用返回;
  • 第二步:判断XXX的前3个字符是否是‘on ’,是则调用on方法绑定事件
  • 第三步:判断XXX的前3个字符是否是‘as ’,是则调用attachBehavior方法设置属性
  • 第四步:遍历行为数组,查找XXX属性,并设置
  • 第五步:是否有getXXX方法,有则抛出InvalidCallException异常
  • 第六步:以上五步均未得到执行,抛出UnknownPropertyException异常
    /**
     * 设置组件属性值
     * 主要分为六步执行:XXX属性名称
     * 第一步:是否有setXXX方法,有则调用返回;
     * 第二步:判断XXX的前3个字符是否是‘on ’,是则调用on方法绑定事件
     * 第三步:判断XXX的前3个字符是否是‘as ’,是则调用attachBehavior方法设置属性
     * 第四步:遍历行为数组,查找XXX属性,并设置
     * 第五步:是否有getXXX方法,有则抛出InvalidCallException异常
     * 第六步:以上五步均未得到执行,抛出UnknownPropertyException异常
     */
    public function __set($name, $value)
    {
        $setter = 'set' . $name;
        if (method_exists($this, $setter)) {
            // 设置属性
            $this->$setter($value);

            return;
        } elseif (strncmp($name, 'on ', 3) === 0) {
            // 绑定事件
            $this->on(trim(substr($name, 3)), $value);

            return;
        } elseif (strncmp($name, 'as ', 3) === 0) {
            // 设置行为
            $name = trim(substr($name, 3));
            $this->attachBehavior($name, $value instanceof Behavior ? $value : Yii::createObject($value));

            return;
        }

        // behavior property
        $this->ensureBehaviors();
        foreach ($this->_behaviors as $behavior) {
            if ($behavior->canSetProperty($name)) {
                $behavior->$name = $value;
                return;
            }
        }

        if (method_exists($this, 'get' . $name)) {
            throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
        }

        throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
    }

 3.__isset魔术方法,检查属性是否定义,执行逻辑分为以下三步:

  • 第一步:检查是否有getXXX方法,有则获取值与null比较
  • 第二步:遍历行为数组,获取属性值与null比较
  • 第三步:返回false
    /**
     * 检查属性是否设置了
     * 主要分为三步执行:XXX属性名称
     * 第一步:检查是否有getXXX方法,有则获取值与null比较
     * 第二步:遍历行为数组,获取属性值与null比较
     * 第三步:返回false
     */
    public function __isset($name)
    {
        //1. 判断getXXX方法
        $getter = 'get' . $name;
        if (method_exists($this, $getter)) {
            return $this->$getter() !== null;
        }
        
        //2. 遍历行为
        $this->ensureBehaviors();
        foreach ($this->_behaviors as $behavior) {
            if ($behavior->canGetProperty($name)) {
                return $behavior->$name !== null;
            }
        }

        //3. 直接返回false
        return false;
    }

4.__unset魔术方法,设置组件属性为null,执行逻辑分为以下三步:

  • 第一步:检查是否有setXXX方法,有则设置null
  • 第二步:遍历行为数组,设置属性为null
  • 第三步:抛出InvalidCallException异常
    /**
     * 设置属性为null
     * 主要分为三步执行:XXX属性名称
     * 第一步:检查是否有setXXX方法,有则设置null
     * 第二步:遍历行为数组,设置属性为null
     * 第三步:抛出InvalidCallException异常
     */
    public function __unset($name)
    {
        //1.setXXX方法
        $setter = 'set' . $name;
        if (method_exists($this, $setter)) {
            $this->$setter(null);
            return;
        }

        //2.遍历行为数组
        $this->ensureBehaviors();
        foreach ($this->_behaviors as $behavior) {
            if ($behavior->canSetProperty($name)) {
                $behavior->$name = null;
                return;
            }
        }

        //3.抛出异常
        throw new InvalidCallException('Unsetting an unknown or read-only property: ' . get_class($this) . '::' . $name);
    }

5.__call魔术方法,遍历行为,调用方法

  • 第一步:遍历行为,判断是否存在$name方法,有则调用返回
  • 第二步:抛出UnknownMethodException异常
    /**
     * 调用类中不存在方法
     * 第一步:遍历行为,判断是否存在$name方法,有则调用返回
     * 第二步:抛出UnknownMethodException异常
     */
    public function __call($name, $params)
    {
        $this->ensureBehaviors();
        foreach ($this->_behaviors as $object) {
            if ($object->hasMethod($name)) {
                return call_user_func_array([$object, $name], $params);
            }
        }
        throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
    }

6.__clone魔术方法,移除clone出来的实例的所有行为

    /**
     * 通过clone一个已存在的对象时,移除其所有行为
     */
    public function __clone()
    {
        $this->_events = [];
        $this->_eventWildcards = [];
        $this->_behaviors = null;
    }

总结:

1.阅读了3个属性

  • $_events 事件数组
  • $_eventWildcards 通配符事件数组
  • $_behaviors 行为数组

2.阅读了6个魔术方法

  • __get 获取组件属性
  • __set 设置组件属性
  • __isset 检查属性是否定义
  • __unset设置属性为null
  • __call 遍历行为,调用方法
  • __clone 克隆实例,并移除新实例中的所有行为
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值