Yii2框架源码研究1-Object

继承树分析

看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)