Laravel 执行流程(三)之 探索 Application 构造函数

发布时间 2023-09-14 16:38:29作者: 珊瑚贝博客
备注:纯手打的学习笔记,如有错误之处请指正,谢谢。希望大家学的开心!

说明:本来应该是说 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 根目录地址,下一章继续深入其他有趣的地方,欢迎关注!

————————————————
原文作者:tlcolorful
转自链接:https://learnku.com/laravel/t/1333/laravel-execution-flow-three-exploring-the-application-constructor
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。