美文网首页yii2Yii2
Yii2框架源码研究1-Object

Yii2框架源码研究1-Object

作者: Vos井宝 | 来源:发表于2016-04-12 14:15 被阅读1104次

    继承树分析

    看yii2框架的源代码会发现,请求的入口,也就是index.php文件,相当的简单,在入口文件中有一行下列代码:

    (new yii\web\Application($config))->run();
    

    这里面实例化了一个Application类的对象,并调用了这个对象的run方法,这篇文章要记录的,就是这个类的来龙去脉。
    想要理清这个类具体是干什么的,首先来分析一下这个类的所有父类,这个类的继承树如下,

    • yii\web\Application
    • yii\base\Application
    • yii\base\Module
    • yii\di\ServiceLocator
    • yii\base\Component
    • yii\base\Object
    • yii\base\Configurable

    这个列表后边的依次是前面的父类。那么现在就从下往上依次研究一下这些类。

    yii\base\Configurable

    这个类只是一个很简单的接口,原代码如下:

    interface Configurable
    {
    }
    

    竟然什么都没有。。。那么这个类的功能到底是什么呢,通过查看注释可以看出,这个Configurable接口其实就是定义了一种约定,所有实现这个接口的类都必须满足一个条件,这个条件就是这个类的构造函数的最后一个参数是一个配置数组,其中key为这个类对应的属性,value为属性对应的值。构造函数需要采用如下的形式:

      public function __constructor($param1, $param2, ..., $config = []) ```
      这个类很简单,接下来继续来看。
    ## yii\base\Object
      先来看一下这个类的方法有哪些:
    ```php
    class Object implements Configurable
    {
    
        public static function className()
        {
            return get_called_class();
        }
        public function __construct($config = [])
        {
            if (!empty($config)) {
                Yii::configure($this, $config);
            }
            $this->init();
        }
        public function init(){
            
        }
        public function __get($name)
        public function __set($name, $value)
        public function __isset($name)
        public function __unset($name)
        public function __call($name, $params)
        public function hasProperty($name, $checkVars = true)   
        public function canGetProperty($name, $checkVars = true)    
        public function canSetProperty($name, $checkVars = true)    
        public function hasMethod($name)
    }
    

    其中只有init是个空方法。需要说明一点的是,yii\base\Object这个类提供了yii2框架所采用的一个非常重要的特性:属性。属性用来表示对象的状态,定义一个属性通常采用如下的方法:

    private $_label;//第一步,定义一个private的属性
    public function getLabel() // 设置get方法,可读属性
    {
        return $this->_label;
    }
    public function setLabel($value) //设置set方法,可写属性
    {
        $this->_label = $value;
    }
    

    上面是对属性这个概念进行分析,Object对象是怎么提供这个特性的呢,这里首先要看一下构造函数中的代码:

    Yii::configure($this, $config);
    

    定位到这个函数:

    public static function configure($object, $properties)
        {
            foreach ($properties as $name => $value) {
                $object->$name = $value;
            }
            return $object;
        }
    

    看起来好简单的样子,遍历,然后属性赋值。当调用类不存在的属性时会调用魔术方法,Object类重载了魔术方法:

        public function __set($name, $value)
        {
            $setter = 'set' . $name;
            if (method_exists($this, $setter)) {
                $this->$setter($value);
            } elseif (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);
            }
        }
    

    当赋值某一个不存在的属性时会去调用相应的set方法,相应的获取某个属性的值会调用get方法。
      每个Object子类如果有构造方法,在其中一定会调用父类的构造方法,并将property数组传递过去,由此终于知道Object类怎么实现属性这个特性了。如果我们想要以及编写的类拥有属性这个特性,首先需要为每一个属性设定相应的get和set方法,然后在实例化的时候传递一个配置数组,将这个数组传递到父类的构造函数就行了。所以在入口文件,实例化Application的时候,传递了一个$config数组,里面的key便是这个Application的一个个属性。
      还需要注意的一点就是,在Object的构造函数中,调用了init方法进行一些初始化,在子类中可以覆盖这个方法进行一些初始化的操作

    相关文章

      网友评论

        本文标题:Yii2框架源码研究1-Object

        本文链接:https://www.haomeiwen.com/subject/uvxwlttx.html