Laravel进阶系列笔记--(一)Laravel生命周期
作者:温新
时间:2021-07-04
hi,我是温新,一名PHPer。
了解完基础系列后,那么有必要来提高一个自己。Laravel太庞大了,基础系列仅仅只是它的一点点。Laravel进阶系列中的内容有许多我是没有用到也没有机会用到,不管用不用的到,那么现在一起重新学习吧。
序言
了解完基础系列后,是否有这样的疑问,Laravel的生命周期是怎么样的?中间件是如何拦截用户请求的?这都将在进阶系列中可以找到答案。
现在来安装一个全新的Laravel项目开启进阶系列的学习吧。
Laravel生命周期剖析
PHP生命周期有五个阶段,而Laravel运行中PHP的第三个生命周期内。
提出PHP生命周期只是为了更好的了解Laravel生命周期,这里不必纠结。
一切从index.php开始
Laravel请求从public/index.php
开始,这也是Laravel生命周期的开始。先来看看index.php
的内容:
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Contracts\Http\Kernel</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Http\Request</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(51, 0, 170)">define</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'LARAVEL_START'</span>, <span style="box-sizing: border-box;color: rgb(51, 0, 170)">microtime</span>(<span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>));</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(51, 0, 170)">file_exists</span>(<span style="box-sizing: border-box;color: rgb(34, 17, 153)">__DIR__</span>.<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'/../storage/framework/maintenance.php'</span>)) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">require</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">__DIR__</span>.<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'/../storage/framework/maintenance.php'</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">require</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">__DIR__</span>.<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'/../vendor/autoload.php'</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">require_once</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">__DIR__</span>.<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'/../bootstrap/app.php'</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$kernel</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">make</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Kernel</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$response</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">tap</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$kernel</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">handle</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">capture</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">))<span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">send</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$kernel</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">terminate</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$response</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span>
第一步:1、请求开始
用户请求到达index.php
,会判断项目是否处于维护状态,若是处于维护状态,那么直接返回并终止请求向下走。
第二步:2、自动加载
这个过程会自动载项目所依赖的第三方组件包。
第三步:3、创建Laravel应用实例
app.php
会创建应用实例。在创建应用实例的过程中会完成注册项目基础服务
、注册服务提供者
、注册目录路径
等工作。
查看app.php
内容:
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 3.1、创建应用实例</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Foundation\Application</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$_ENV</span>[<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'APP_BASE_PATH'</span>] <span style="box-sizing: border-box;color: rgb(152, 26, 26)">??</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">dirname</span>(<span style="box-sizing: border-box;color: rgb(34, 17, 153)">__DIR__</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 3.2、完成内核绑定</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">singleton</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Contracts\Http\Kernel</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">App\Http\Kernel</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">singleton</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Contracts\Console\Kernel</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">App\Console\Kernel</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">singleton</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Contracts\Debug\ExceptionHandler</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">App\Exceptions\Handler</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span>;</span>
app.php
完成两个部分的工作,分别是创建应用实例
与绑定内核到APP服务容器
。
3.1、查看实例化应用实例类
创建应用实例时会去实例化Illuminate\Foundation\Application
类,在创建应用实例前会完成基础路径的注册
、基础服务提供者的注册
、注册核心容器别名`的注册工作并将其绑定到应用容器。
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// Illuminate\Foundation\Application.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">__construct</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$basePath</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">null</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$basePath</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">setBasePath</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$basePath</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">registerBaseBindings</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">registerBaseServiceProviders</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">registerCoreContainerAliases</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>
服务提供者在此阶段注册
3.2、内核绑定
Laravel根据请求类型的不同,将请求发送到HTTP内核或Console内核。不管是哪一个请求,其最终的作用都是接收一个HTTP请求,并返回一个响应结果。
HTTP内核继承自Illuminate\Foundation\Http\Kernel
,在这个类中定义了一个$bootstrappers
数组,这个数组中的类在请求被执行前运行。
HTTP内核还定义了中间件,所有请求都会经过HTTP中间件,Laravel拦截HTTP请求就是在这个地方进行拦截。
第四步:请求与响应
应用容器
注册完成后,进入请求接收与响应
阶段:
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 请求接收与响应</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$kernel</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">make</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Kernel</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$response</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">tap</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$kernel</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">handle</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">capture</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">))<span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">send</span>();</span>
当请求走到$kernel = $app->make(Kernel::class);
这时,看到它做了什么。
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">__construct</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Application</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Router</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$router</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">app</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$app</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">router</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$router</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">syncMiddlewareToRouter</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>
内核在实例化时,构造函数中将中间件组
注册到路由,注册完毕后就可以利用这些中间件对请求进行过滤。
4.1、处理HTTP请求
<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 处理请求</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$response</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">tap</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$kernel</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">handle</span>(</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建请求实例</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">capture</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">))<span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">send</span>();</span>
一旦应用被启动且所有服务提供者被注册,Request
将会被交给路由进行分发,路由器将分发请求到路由或控制器,同时运行所有路由指定的中间件。
我是温新
每天进步一点点,就一点点