laravel
laravel copied to clipboard
02. HTTP Kernel Handle 解析
Kernel Handle
App\Http\Kernel
继承自 Illuminate\Foundation\Http\Kernel
类,所以本文章的分析主要集中在 app/Http/Kernel.php 和 vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php 两个类中
__construct 解析
因为 App\Http\Kernel
没有 __construct 方法,所以穿透到了 Illuminate\Foundation\Http\Kernel
的 __construct:
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L82-L103
首先是此方法传入参数的 __construct(Application $app, Router $router)
声明,这里恰好使用了 Laravel 容器的依赖注入(Dependency Injection,Inversion of Control的一种)设计。具体的在本篇不讲述,可参见本篇末尾的单独分析的链接的文章。
执行到 __construct 时, Illuminate\Foundation\Application
容器会将 Illuminate\Foundation\Application
(即应用容器自身)和 Illuminate\Routing\Router
注入到方法内。然后逻辑代码将两个对象赋给 App\Http\Kernel
的 $this
属性中。
然后将 Illuminate\Foundation\Http\Kernel
的 $middlewarePriority 属性
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L66-L80
赋值给 Illuminate\Routing\Router
的 $middlewarePriority 属性
根据其注释,此属性是强制对 middleward 中间件执行顺序进行排序的作用。
在后面将 App\Http\Kernel
中声明的 $middlewareGroup
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/app/Http/Kernel.php#L24-L44
在 Illuminate\Foundation\Http\Kernel
的 96-98行,调用 Illuminate\Routing\Router
的 middlewareGroup 方法,存到 $router 的 $middlewareGroup 中
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Routing/Router.php#L854-L866
紧接着,将
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/app/Http/Kernel.php#L46-L63
的中间件,调用 Illuminate\Routing\Router
的 aliasMiddleware 的方法,绑定到 $router 的 $middleware 中
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Routing/Router.php#L819-L831
至此, Kernel::__construct()
解析完毕。
handle 解析
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L105-L132
调用到 Symfony\Component\HttpFoundation\Request
的 enableHttpMethodParameterOverride 方法
Illuminate\Http\Request
继承自Symfony\Component\HttpFoundation\Request
并且Illuminate\Http\Request
未覆盖 enableHttpMethodParameterOverride
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/symfony/http-foundation/Request.php#L638-L652
然后,调用 Illuminate\Foundation\Http\Kernel
的 sendRequestThroughRouter
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L134-L152
通过第142行,将 $request 注入进 Illuminate\Foundation\Application
容器。
144行,将门面类中的 request
数据清理掉
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L164-L173
Bootstrap 解析
然后146行,调用 Illuminate\Foundation\Http\Kernel
的 bootstrap 方法
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L154-L164
第161执行到容器的 hasBeenBootstrapped 方法 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Application.php#L249-L257
第162实际得到这个数组
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L31-L43
然后将数组做为参数,执行容器的 bootstrapWith
方法
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Application.php#L193-L210
特别留意206行的 make
调用
关于容器
make
方法的细节 请查阅 10. 容器的 singleton 和 bind 的实现 的 “揭开 Container::make() 神秘的面纱” 段落
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Application.php#L716-L734
关于 loadDeferredProvider 的逻辑会最终执行到
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Application.php#L691-L714
第710行的 booting 方法,是登记一个闭包 (并不会马上执行这个闭包), 然后这个服务提供者在 boot()
阶段的 $this->fireAppCallbacks($this->bootingCallbacks)
才会真正被创建。 关联阅读请见 04. ServiceProvider Boot 解析
然后结果就是依次执行
-
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables
-
\Illuminate\Foundation\Bootstrap\LoadConfiguration
-
\Illuminate\Foundation\Bootstrap\HandleExceptions
-
\Illuminate\Foundation\Bootstrap\RegisterFacades
-
\Illuminate\Foundation\Bootstrap\RegisterProviders
-
\Illuminate\Foundation\Bootstrap\BootProviders
这些 Bootstrap 类的 bootstrap 方法
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/LoadEnvironmentVariables.php#L13-L35 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php#L14-L52 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php#L22-L43 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/RegisterFacades.php#L12-L28 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/RegisterProviders.php#L9-L18 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/BootProviders.php#L9-L18
上面列出的清单中,分别作用为
类 | 作用 |
---|---|
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables |
加载环境变量 |
\Illuminate\Foundation\Bootstrap\LoadConfiguration |
加载config |
\Illuminate\Foundation\Bootstrap\HandleExceptions |
错误处理者 |
\Illuminate\Foundation\Bootstrap\RegisterFacades |
注册门面类 |
\Illuminate\Foundation\Bootstrap\RegisterProviders |
注册服务提供者 |
\Illuminate\Foundation\Bootstrap\BootProviders |
启动服务提供者 |
其中最后两项在 laravel 请求的生命周期中是至关重要的,我们将在后续文章中重点讲解。
在 bootstrap
阶段结束后,Kernel::sendRequestThroughRouter
后面带 pipeline
关键字的代码就是管道。
关于管道请查阅 05. Pipeline 解析
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L148-L151
在进入管道前, 调用了 dispatchToRouter
返回一个闭包对象
https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php#L166-L178
匹配路由的逻辑清晰可见 https://github.com/xiaohuilam/laravel/blob/d081c918b7e582ec5b3f94316f44834466cec37d/vendor/laravel/framework/src/Illuminate/Routing/Router.php#L601-L682
如果一路抽丝剥茧,我们便能找到 Router 调用 controller 的逻辑了。 请见06. RouteServiceProvider 详解 最后段落。