Laravel 执行流程(三)之 探索 Application 构造函数
备注:纯手打的学习笔记,如有错误之处请指正,谢谢。希望大家学的开心!
说明:本来应该是说 Container 类(下)的,不过经过学习,直接看这个类实在不好理解,一会是绑定,一会共享实例,真心不知道说的什么....还是先从程序的入口处,顺藤摸瓜,用到的时候再结合上下文理解,比较容易消化,希望理解,抱歉!
- OK,从入口地址 public/index.php 看到如下代码:
注释很有趣,翻译凑合看吧。
则现在我们打开 bootstarp/app.php 文件,因为这是 $app
这个玩意儿的出生地。
咱们就从在这里摸索一下构造函数里面发生了什么,则打开 Application.php
文件。
再次给各位学友提示一次:怎么找具体文件我就略过了,前面都具体说过,一般看见命名空间,基本就可以找到对应的文件路径。
如现在打开的 Application.php
是位于 vendor/laravel/framework/src/Illuminate/Foundation/Application.php
,而命名空间是 Illuminate\Foundation
。
Application类的构造函数截图如下:
因为代码量真的很多,如果每一点都要说,不仅会看得云里雾里,还不一定能理解,所以,我这里以总结的方式概述,特别值得学习的地方再单独提出来说。
一、registerBaseBindings()
注册一些基本的绑定到容器中。
简单点说,此方法内部进行3次赋值,赋值后的变量及变量内容形式如下:
Container::$instance = $this
$this->instances['app'] = $this
$this->instances['Illuminate\Container\Container'] = $this
变量名具体含义:
$this,也就是 Application 类。
Container::$instance,之前说过 Application 是 Container 的子类,而 $instance 静态变量是在 Container 类中已经定义好的,截图示:
$this->instances,也是在 Container 中定义的,含义为存放容器的共享实例,截图示:
你可以在 registerBaseBindings 方法的最后面打印如下3个变量进行检测,得到的都是 application object,
到此,所谓的基本绑定结束,还是云里雾里的,英文不好只能看代码了,反正你记住父类的2个成员属性已经得到了 application 对象。
二、registerBaseServiceProviders()
注册所有的基础服务提供商。
好吧,第二章提过的 ioc 容器=地基,开始买材料准备施工,找几个最基础的供应商商来进行合作,搞水泥的啊,砌砖的啊,以后有更多的需求,根据自己的需求在去找供应商谈。Laravel 刚开始注册了2个提供商,一个事件,一个是路由。
我们先意淫一下大概的意思,找到了供应商,准备合作签合同( register
),先和搞水泥的签( event
),在和砌砖的签( routing
),和谁签?I'm the boss( $this
)。
既然我是老板,合同条款肯定得看清楚了,咱们去看看合同先( register方法
)
嗯!合同说的很清楚,首先确定我和供应商是否签过合同了,签过了( getProvider()
来判断)就滚蛋,浪费时间;虽然我是老板,但不是法人,你打个电话叫他过来,名字叫狗蛋(resolveProviderClass
方法,如果 $provider
为 string 类型,则根据提供的类名帮供应商实例化并 return),如图
OK,差不多,狗蛋把字一签( $provider->register()
),供应商算是正式入驻施工团队了,当然了,合同还说明以后要是有其他要改的地方,直接填一份声明即可,$options
是 register方法
的第二个参数。
既然签了合同,就要如公司档案,狗蛋屁颠屁颠的跑去档案室了($this->markAsRegistered($provider)
)标记为已注册;好,大功告成( return $provider
)。
至此,合同也签好了,其实还有很多地方没提到,提到的话就跑题了。
三、registerCoreContainerAliases()
注册核心容器的别名。
嗯,这个简单的多,还有啥好说的呢,定义容器里面一些核心类的别名,有兴趣直接去看这个方法就行。图示:
当然了最后是存放在 $aliases
这个数组里面哟,在 container 定义的成员属性。
四、setBasePath()
设置基本路径。
这个更简单了,这就是前面说 $app
出生地的地方,传了一个路径参数,如图:
就是把参数赋值给 $basePath
成员属性,值得一提的是 bindPathsInContainer()
方法,很灵活,在容器内绑定路径,怎么个绑定法?图示:
这里用 basePath 举例说明,先是在 $this->instances[‘path’]
单元绑定一个当前 laravel 根目录路径的这样一个字符串,接着把常用的,如基本路径,配置路径,数据库路径等 key 名称组成一个数组 foreach 循环,然后关键来了,把 foreach 里面的代码简易化就是: $this->instance(path.base,$this->basePath())
,而 basePath 方法也是早就定义好的,代码一句话:
这样一来,刚才赋值的 basePath 成员属性返回即可。还有一些 databasePath,langPath,publicPath 都可以去看看,挺有趣。
至此,$app
终于生出来了,绑定了 application 对象,和2个供应商签了合同,给一些核心类起了别名,配置了 laravel 根目录地址,下一章继续深入其他有趣的地方,欢迎关注!