Laravel 底层是如何处理HTTP请求
一、概述
web 服务器对 HTTP 请求的处理流程大体上都是这样的:在某个端口监听请求,请求进入后运行程序,然后将程序运行结果以响应的形式发送出去。
Laravel 框架构建的 Web 应用处理 HTTP 请求的流程亦是如此。所有 HTTP 请求都会被转发到单入口文件 /public/index.php。
二、剖析
逐行分析 index.php 的代码。
1、引入自动加载
require __DIR__.'/../vendor/autoload.php';
2、创建一个 Application 实例,作为全局的服务容器,并将处理请求的核心类Kernel实现实例 绑定到该容器中。
$app = require_once __DIR__.'/../bootstrap/app.php';
注:app.php文件内的处理:
<?php // 创建一个 Application 实例 $app = new Illuminate\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__) ); // 绑定处理HTTP请求的接口实现 到服务容器 $app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class ); // 绑定处理CLI请求的接口实现 到服务容器 $app->singleton( Illuminate\Contracts\Console\Kernel::class, App\Console\Kernel::class ); $app->singleton( Illuminate\Contracts\Debug\ExceptionHandler::class, App\Exceptions\Handler::class ); // 返回应用程序实例 return $app;
3、从服务容器中解析处理 HTTP 请求的 Kernel 实例
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
这里的 make 方法在 Illuminate\Foundation\Application 中,作用就是解析
4、处理 HTTP 请求的核心代码
$response = $kernel->handle( $request = Illuminate\Http\Request::capture() );
$kernel
是 App\Http\Kernel 的父类,即 Illuminate\Foundation\Http\Kernel,我们进入到 handle() 方法
/** * 处理传入的http请求,获取一个 Request,返回一个 Response * 输入http请求,返回http响应 * * Handle an incoming HTTP request. * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function handle($request) { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new RequestHandled($request, $response) ); return $response; }
我们发现实际进行处理的是 sendRequestThroughRouter() 这个方法
protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); // 在发送请求到路由之前,先调用 bootstrap() 方法运用应用的启动类 $this->bootstrap(); /** * 以管道模式来处理 HTTP 请求 * * 全局中间件都校验通过才会将请求分发到路由器进行处理 * 路由器会将请求 URL 路径与应用注册的所有路由进行匹配,如果有匹配的路由,则先收集该路由所分配的所有路由中间件 * 通过这些路由中间件对请求进行过滤,所有路由中间件校验通过才会运行对应的匿名函数或控制器方法,执行相应的请求处理逻辑 * 最后准备好待发送给客户端的响应。 */ return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }
5、发送响应
$response->send();
6、终止程序,做一些善后清理工作(主要包括运行终止中间件,以及注册到服务容器的一些终止回调)
$kernel->terminate($request, $response);
链接:https://mp.weixin.qq.com/s/MJDo0MXPTN2fpfVzJZ42Og