一个 Laravel 请求的完整生命周期
概述
Laravel 的生命周期从public\index.php
开始,从public\index.php
结束。
下面是 public\index.php
的全部源码,更具体来说可以分为四步:
1. require __DIR__.'/../bootstrap/autoload.php';
2. $app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
3. $response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
4. $kernel->terminate($request, $response);
Laravel 的请求步骤,以下是四步详细的解释是:
- composer自动加载需要的类,文件载入composer生成的自动加载设置,包括所有你
composer require
的依赖。 - 生成容器Container,Application实例,并向容器注册核心组件(HttpKernel,ConsoleKernel ,ExceptionHandler)(对应代码2,容器很重要,后面详细讲解)。
- 处理请求,生成并发送响应(对应代码3,毫不夸张的说,你99%的代码都运行在这个小小的handle 方法里面)。
- 请求结束,进行回调(对应代码4,还记得可终止中间件吗?没错,就是在这里回调的)。
详细解释
第一步:注册加载composer自动生成的class loader
就是加载初始化第三方依赖。
第二步:生成容器 Container
并向容器注册核心组件,是从 bootstrap/app.php
脚本获取 Laravel 应用实例,
第三步:这一步是重点,处理请求,并生成发送响应。
请求被发送到 HTTP
内核或 Console
内核,这取决于进入应用的请求类型。
取决于是通过浏览器请求还是通过控制台请求。这里我们主要是通过浏览器请求。
HTTP 内核的标志性方法 handle处理的逻辑相当简单:获取一个
Request
,返回一个Response
,把该内核想象作一个代表整个应用的大黑盒子,输入 HTTP 请求,返回 HTTP 响应。
1. 首先 Bootstrap 检测环境,加载 bootstrapper
数组中的一些配置
HTTP 内核继承自 Illuminate\Foundation\Http\Kernel 类,该类定义了一个 bootstrappers 数组,这个数组中的类在请求被执行前运行,这些 bootstrappers 配置了错误处理、日志、检测应用环境以及其它在请求被处理前需要执行的任务。
protected $bootstrappers = [
//注册系统环境配置 (.env)
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
//注册系统配置(config)
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
//注册日志配置
'Illuminate\Foundation\Bootstrap\ConfigureLogging',
//注册异常处理
'Illuminate\Foundation\Bootstrap\HandleExceptions',
//注册服务容器的门面,Facade 是个提供从容器访问对象的类。
'Illuminate\Foundation\Bootstrap\RegisterFacades',
//注册服务提供者
'Illuminate\Foundation\Bootstrap\RegisterProviders',
//注册服务提供者 `boot`
'Illuminate\Foundation\Bootstrap\BootProviders',
];
注意顺序:
Facades
先于ServiceProviders
,Facades
也是重点,后面说,这里简单提一下,注册Facades
就是注册config\app.php
中的aliases
数组,你使用的很多类,如Auth
,Cache
,DB
等等都是Facades
;而ServiceProviders
的register
方法永远先于boot
方法执行,以免产生boot
方法依赖某个实例而该实例还未注册的现象。
HTTP 内核还定义了一系列所有请求在处理前需要经过的 HTTP 中间件,这些中间件处理 HTTP 会话的读写、判断应用是否处于维护模式、验证 CSRF 令牌等等。
2. 第一堵墙,全局中间件,默认为 CheckForMaintenanceMode
在Laravel基础的服务启动之后,就要把请求传递给路由了。路由器将会分发请求到路由或控制器,同时运行所有路由指定的中间件。
传递方式
传递给路由是通过 Pipeline
(管道)来传递的,但是Pipeline有一堵墙,在传递给路由之前所有请求都要经过,这堵墙定义在app\Http\Kernel.php
中的$middleware
数组中,没错就是中间件,默认只有一个CheckForMaintenanceMode
中间件,用来检测你的网站是否暂时关闭。这是一个全局中间件,所有请求都要经过,你也可以添加自己的全局中间件。
3. 然后遍历所有注册的路由,找到最先符合的第一个路由
然后遍历所有注册的路由,找到最先符合的第一个路由,
4. 第二堵墙,通过该路由的中间件(组)
经过该路由中间件,进入到控制器或者闭包函数,执行你的具体逻辑代码。
所以,当请求到达你写的代码之前,Laravel已经做了大量工作,请求也经过了千难万险,那些不符合或者恶意的的请求已被Laravel隔离在外。