灰太狼 2019-04-01 17:15:57 542次浏览 0条回复 1 1 0

先从一个地址讲起例如下面的地址:

yii一个地址 http://yii4.local.com/index.php?XDEBUG_SESSION_START=1 返回结果:页面显示 12345678

这个结果怎么显示的呢?如果我们自己写一个 index.php 然后里面写 echo 12345678 一样达到效果。

这里说的不是这么简单,包含了请求,处理,响应三个阶段。而yii的其他部分组件全部摘除了(保留了核心的容器,服务提供器等)

首先查看 web 目录下的 index.php 会看 new 了一个 yii\web\Application($config)

然后执行->run();

yii\web\Application的父类是 yii\base\Application,看一下父类的构造函数 只看里面的 $this->preInit(&$config);(现在还不熟悉看其他的会很迷糊) 在 preInit() 里都做了什么呢?只看 preInit() 方法里的 foreach($this->coreComonents() as $id=>$component) 这里的意思是yii内部使用的组件先要加载进去。(加载这个词看似很屌),就解释一下 “加载”。

1 在讲“加载”之前先交代一下yii封装好的容器(容器就是你给他一个类地址或回调)它返回给你这个类的对象(同时如果类有依赖会自动解决依赖,不用你操心)。这个容器也不先不用管。只知道它这个作用就行。

2 再将yii利用了php的魔术函数__get(),__set()(当获取一个属性不存在时自动执行)

然后回到上面的

foreach($this->coreComonents() as $id=>$component) 
{

}

$this->coreComonents() (在 yii\web\Application 里有这个方法,父类也有)里面定义了request和response 这两个就是yii的请求和响应。

然后开始上面的 foreach 循环就是把这个定义好的组件放到 $config 数组里。(这里的 $config 数组就是项目下main.php的配置项目,只不过yii在这里而外追加了一些必须的配置)。注意上面数组的key是:components写死的这里后面会讲。

好了,现在 $confgi 有内容了就是key组件名,value是组件的类命名空间地址。

然后执行了 Component::__construct($config); (也就是$config内容都准备好了,开始发动把)

在往里看。看到了 Yii::config($this,$config); 这句就是给当前对象 $this 的属性赋值。 而 $this 的属性是什么呢?就是 $config 里的 key 值。记得上面提到的注意的 components 了吧。 其实现在的 $config 样子大概是

$config = [
    'components' => ['request' => ['class'=>'yii\web\Request']]
]

//下面是重点
public static function configure($object,$properties)
{
    foreach($properties as $name => $value){
    
      $object->$name = $value 
      //实际执行的是 $this->components = ['request' => ['class'=>'yii\web\Request']]
}

但是 yii/web/Application 里面没有定义 components 这个属性啊

会看上面讲的,如果php访问未定义的属性会访问 __get() ,如果给未定义的属性赋值会执行 __set().

__get()__set() 在哪里了呢?看 yii\base\Application 的父类是 yii\base\Module->yii\base\module->yii\di\ServiceLocator->yii\base\Component 好了,在Component类里面会看到这两个__get(),和 __set() 方法。

上面执行 $this->components = ['request' => ['class'=>'yii\web\Request']] 没有这个components方法,那么就通过 __set(). 在前面价格set变成 setComponents();

最后看看有没有这个方法,发现有:在看 yii\base\Application 的父类是 yii\base\Module->yii\base\module->yii\di\ServiceLocatorserviceLocator 里。

这里又一个foreach()。而这里的foreach就是对每个组件的定义赋值. 循环的内容是:['request' => ['class'=>'yii\web\Request']]

把这个 key=>value 先放到一个数组里$this->_definitions

然后就不管里。 然后后面执行->run() (上面提到了,也就是大概初始化过程完事了)

把请求和响应组件定义都放在数组里准备好了,如果有地方用到就去实例化;

run里用到了request $this->getRequest();这时候就回去容器里要一个对象 要哪个对象呢。

public function getRequest()
{
    $this->get('request');  //这个key也就是前面初始化组件的key
}

然后容器根据key找到了value['class'=>'yii\web\Request']然后根据这个地址就能实例化了。然后 $request对象就获取到了。然后根据$request对象去解析请求地址里包含的模型,控制器,方法(action) 然后执行action把结果赋值给response->data。这里的response对象和request对象获取逻辑一样。 然后respons里会echo $this->content;在这之前会把$response->data(是执行action的返回值)的值给$response->content。。然后在执行echo $this->content时就会输出action的内容了。

觉得很赞
亿速云
    没有找到数据。
您需要登录后才可以回复。登录 | 立即注册