加入收藏 | 设为首页 | 会员中心 | 我要投稿 南京站长网 (https://www.025zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Yii2中组件的注册与创建方法

发布时间:2021-03-18 16:36:06 所属栏目:PHP教程 来源:网络整理
导读:副标题#e# 今天本来打算研究一下yii2.0的AR模型的实现原理,然而,计划赶不上变化,突然就想先研究一下yii2.0的数据库组件创建的过程。通过对yii源码的学习,了解了yii组件注册与创建的过程,并发现原来yii组件注册之后并不是马上就去创建的,而是待到实际
副标题[/!--empirenews.page--]

 今天本来打算研究一下yii2.0的AR模型的实现原理,然而,计划赶不上变化,突然就想先研究一下yii2.0的数据库组件创建的过程。通过对yii源码的学习,了解了yii组件注册与创建的过程,并发现原来yii组件注册之后并不是马上就去创建的,而是待到实际需要使用某个组件的时候再去创建对应的组件实例的。本文大概记录一下这个探索的过程。

  要了解yii组件的注册与创建,当然要从yii入口文件index.php说起了,整个文件代码如下:

run();

可以看到入口文件引入了几个配置文件,并将所有配置文件的内容都合并到$config这个配置数组中,然后使用这个配置数组作为参数去创建一个应用实例。若将这个配置数组打印出来,就会看到,“components”下标对应的元素包含了yii组件的参数信息(这里只截图一小部分):

这些组件的信息是在引入进来的几个配置文件中配置的,Yii组件就是使用这些参数信息进行注册与创建的。

  接下来就进入yiiwebApplication类的实例化过程了,yiiwebApplication类没有构造函数,但是它继承了yiibaseApplication类:

所以会自动执行yiibaseApplication类的构造函数:

state = self::STATE_BEGIN; $this->preInit($config); $this->registerErrorHandler($config); Component::__construct($config); }

这里要顺便说一下预初始化方法preInit(),它的代码如下:

coreComponents() as $id => $component) { if (!isset($config['components'][$id])) { $config['components'][$id] = $component; } elseif (is_array($config['components'][$id]) && !isset($config['components'][$id]['class'])) { $config['components'][$id]['class'] = $component['class']; } } }

  这个函数对传递给构造函数的配置数组$config进行了一些预处理操作(这里省略了),最后使用coreComponents()方法返回的数组对$config数组进行了完善,coreComponents()方法是这样的:

['class' => 'yiilogDispatcher'],'view' => ['class' => 'yiiwebView'],'formatter' => ['class' => 'yiii18nFormatter'],'i18n' => ['class' => 'yiii18nI18N'],'mailer' => ['class' => 'yiiswiftmailerMailer'],'urlManager' => ['class' => 'yiiwebUrlManager'],'assetManager' => ['class' => 'yiiwebAssetManager'],'security' => ['class' => 'yiibaseSecurity'],]; }

  其实就是一些核心组件的配置,也就是说这些组件是可以不需要我们在配置文件中配置的,yii会自动进行注册。

  好了,回到yiibaseApplication类的构造函数,这个函数最后调用了yiibaseComponent类的构造函数,但yiibaseComponent类是没有构造函数的,不过它继承了yiibaseObject类:

所以也自动执行了yiibaseObject类的构造函数:

init();}

这里主要是调用了yiiBaseYii类的静态方法configure():

$value) { $object->$name = $value; } return $object; }

这个方法就是循环入口文件(new yiiwebApplication($config))->run();中的$config数组(这个数组的结构参见本文第一个截图),以数组键名作为对象属性名,对应的键值作为对象属性值进行赋值操作。所以当循环到组件配置参数的时候是这样子的:$object->components = $value($value为所有组件的配置数组),也就是对$object的components属性进行赋值操作,那这个$object是哪个类的对象呢?回想最初调用的源头,其实它就是入口文件中需要进行实例化的yiiwebApplication类的对象啊。然而,这个类和它的祖先类都没有components这个成员变量啊,不急,又要进行一番继承套路了,顺着yiiwebApplication类的继承关系一层一层往上找可以发现yiiwebApplication类最终也继承了yiibaseObject类,yiibaseObject类是支持属性的,所以yiiwebApplication类也支持属性(关于属性,可以参考我的另一篇博文:yii2之属性),当赋值操作找不到components成员变量时会调用setComponents()方法,又去找这个方法的所在,终于在它的祖先类yiidiServiceLocator中找到了setComponents()方法,没错,对应用实例的components属性进行赋值操作其实就是调用这个方法!

  好了,现在就来看看setComponents()这个方法到底干了啥:

$component) { $this->set($id,$component); } }

其实很简单,就是循环各个组件的配置数组,调用set()方法,set()方法如下:

_components[$id]); if ($definition === null) { unset($this->_definitions[$id]); return; } if (is_object($definition) || is_callable($definition,true)) { // an object,a class name,or a PHP callable $this->_definitions[$id] = $definition; } elseif (is_array($definition)) { // a configuration array if (isset($definition['class'])) { $this->_definitions[$id] = $definition; } else { throw new InvalidConfigException("The configuration for the "$id" component must contain a "class" element."); } } else { throw new InvalidConfigException("Unexpected configuration type for the "$id" component: " . gettype($definition)); } }

其实就是把组件配置存入$_definitions这个私有成员变量(即注册),然后呢?然后就没有下文了。。。

(编辑:南京站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读