【php-yii2类继承关系】

yii\web\Application->yii\base\Application->yii\base\Module->yii\di\ServiceLocator->yii\base\Component->yii\base\Object->yii\base\Configurable  

yii->yii\BaseYii,继承的来源

Yii.php

require(__DIR__ . '/BaseYii.php');

/**
 * Yii is a helper class serving common framework functionalities.
 *
 * It extends from [[\yii\BaseYii]] which provides the actual implementation.
 * By writing your own Yii class, you can customize some functionalities of [[\yii\BaseYii]].
 *
 * @author Qiang Xue 
 * @since 2.0
 */
class Yii extends \yii\BaseYii
{
}


最顶类是接口类型Configurable,如下:

  interface Configurable{

}


数据库连接组件分析:

yii\db\Connection 是继承yii\base\Component,为什么要继承Component呢?

解答:因为Component有__set函数,

1、将组件配置参数components数组通过setComponents()函数转化为组件对象集合

入口文件分析:

index.php

$config = yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/../../../core/common/config/main.php'),
    ...
);
$application = new yii\web\Application($config);

yii\web\Application继承的是yii\baseApplication的构造函数

namespace yii\base

Application.php

public function __construct($config = [])
    {
	/*..*/
        Component::__construct($config);
    }

Component继承yii\base\Object构造函数并执行

namespace yii\base

Object.php

public function __construct($config = [])
    {
        if (!empty($config)) {
            Yii::configure($this, $config);
        }
        ..
    }
这里的$this是yii\web\Application实例


Yii继承BaseYii,并且执行configure的函数

namespace yii;

BaseYii.php文件

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

        return $object;
    }

这里对对象属性赋值,由一开始提到的继承关系追溯可以知道, yii\web\Application都继承了yii\base\Component,yii\base\Component,所以会用到yii\base\Component类的__set()函数,继而用到 yii\di\ServiceLocator类的 setComponents(),这里的$object是yii\web\Application实例,$properties是配置参数数组,其中包含components键值


 public function __set($name, $value)
    {
        $setter = 'set' . $name;
        if (method_exists($this, $setter)) {
            // set property
            $this->$setter($value);

            return;
        } }
这里的$name='components'

$value=组件配置参数:

因为构造函数里面的$value = common\config\main.php的如下信息


'component' => [

	'db' => [

		'class' => 'yii\db\Connection',

		'dsn'=>'mysql:dbname=mhk;host=127.0.0.1',

		'username'=>'root',

		'password'=>'password'

	]

];
setComponents()函数:设置各个组件的参数为value,各个组件的名字为key,保存在

$this->_definitions变量里

ServiceLocator.php

namespance yii\di
	
	 public function setComponents($components)
    	{
        	foreach ($components as $id => $component) {
            		$this->set($id, $component);
       		 }
    	}

yii::$app->db的会后会调用yii\di\ServiceLocator的__get()

 public function __get($name)
    {
        if ($this->has($name)) {
            return $this->get($name);
        } else {
            return parent::__get($name);
        }
    }

 public function get($id, $throwException = true)
    {
        if (isset($this->_components[$id])) {
            return $this->_components[$id];
        }

        if (isset($this->_definitions[$id])) {
            $definition = $this->_definitions[$id];
            if (is_object($definition) && !$definition instanceof Closure) {
                return $this->_components[$id] = $definition;
            } else {
                return $this->_components[$id] = Yii::createObject($definition);
            }
        } elseif ($throwException) {
            throw new InvalidConfigException("Unknown component ID: $id");
        } else {
            return null;
        }
    }
Yii::createObject($definition)
这个就是为各个组件根据配置的参数来创建各个组件对象,并保存到$this->_components变量

下次再调用yii::$app->db时候就直接从这个变量取到了

public function has($id, $checkInstance = false)
    {
        return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]);
    }
至于创建对象的方法createObject()

public static function createObject($type, array $params = [])
    {
        if (is_string($type)) {
            return static::$container->get($type, $params);
        } elseif (is_array($type) && isset($type['class'])) {
            $class = $type['class'];
            unset($type['class']);
            return static::$container->get($class, $params, $type);
        } elseif (is_callable($type, true)) {
            return static::$container->invoke($type, $params);
        } elseif (is_array($type)) {
            throw new InvalidConfigException('Object configuration must be an array containing a "class" element.');
        }

        throw new InvalidConfigException('Unsupported configuration type: ' . gettype($type));
    }
用容器去获取对象的,容器的概念就是依赖注入了。就是利用反射机制的构造函数参数注入原理

$reflectionClass = new ReflectionClass("Bar"); 
        
        return $reflectionClass->newInstanceArgs(array($this, $this->arr)); 






你可能感兴趣的:(php)