合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
[TOC] ![](https://box.kancloud.cn/51d527189c9841f2dc6ec55fb0234267_1890x956.png) Laravel 的生命周期从`public\index.php`开始,从`public\index.php`结束。 ~~~php // 阶段一 require __DIR__.'/../bootstrap/autoload.php'; // 阶段二 $app = require_once __DIR__.'/../bootstrap/app.php'; $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); // 阶段三 $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send(); // 其它 $kernel->terminate($request, $response); ~~~ ## **1. 加载项目依赖** 现代 PHP 依赖于 Composer 包管理器,入口文件通过引入由 Composer 包管理器自动生成的类加载程序,可以轻松注册并加载项目所依赖的第三方组件库。 所有组件的加载工作,仅需一行代码即可完成: ~~~php require __DIR__.'/../vendor/autoload.php'; ~~~ ## **2. 创建 Laravel 应用实例** 创建应用实例(或服务容器),由位于 `bootstrap/app.php` 文件里的引导程序完成,创建服务容器的过程即为应用初始化的过程,项目初始化时包括:注册项目基础服务、注册项目服务器提供的别名、注册目录路径等在内的一些注册工作。 下面是`bootstrap/app.php`的代码,包含两个主要部分「创建应用实例」和「绑定内核至 APP 服务容器」: ~~~php <?php // 第一部分: 创建应用实例 $app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') ); // 第二部分: 完成内核绑定 $app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class ); $app->singleton( Illuminate\Contracts\Console\Kernel::class, App\Console\Kernel::class ); $app->singleton( Illuminate\Contracts\Debug\ExceptionHandler::class, App\Exceptions\Handler::class ); return $app; ~~~ ### **2.1 创建应用实例** 创建应用实例即实例化 `Illuminate\Foundation\Application` 这个服务容器(**APP容器**),其中包括:注册应用的基础路径并将路径绑定到 **APP容器**、注册基础服务提供者到**APP容器**、注册核心容器别名到**APP容器** ~~~php /** * Create a new Illuminate application instance. * * @param string|null $basePath * @return void */ public function __construct($basePath = null) { if ($basePath) { $this->setBasePath($basePath); } $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); } ~~~ ### **2.2 内核绑定** Laravel 会依据 HTTP 请求的运行环境的不同,将请求发送至相应的内核: **HTTP 内核** 或 **Console 内核**。无论 HTTP 内核还是 Console 内核,它们的作用都是是接收一个 HTTP 请求,随后返回一个响应。 ## **3. 接收请求并响应** ~~~php $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send(); ~~~ ### **3.1 解析内核实例** 在第二阶段我们已经将 **HTTP 内核** 和 **Console 内核** 绑定到了 **APP 容器**,使用时通过 APP 容器 的 `make() ` 方法将内核解析出来,解析的过程就是内核实例化的过程。 ~~~php $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); ~~~ 进一步挖掘 `Illuminate\Foundation\Http\Kernel` 内核的 `__construct(Illuminate\Contracts\Foundation\Application $app, \Illuminate\Routing\Router $router)` 构造方法,它接收 APP 容器 和 路由器 两个参数。 ~~~php /** * Create a new HTTP kernel instance. * * @param \Illuminate\Contracts\Foundation\Application $app * @param \Illuminate\Routing\Router $router * @return void */ public function __construct(Application $app, Router $router) { $this->app = $app; $this->router = $router; $this->syncMiddlewareToRouter(); } ~~~ 在实例化内核时,构造函数内将在 HTTP 内核定义的「中间件组」注册到 **路由器**,注册完后就可以在实际处理 HTTP 请求前调用这些「中间件」实现 **过滤 请求**的目的。 ~~~php /** * Sync the current state of the middleware to the router. * * @return void */ protected function syncMiddlewareToRouter() { $this->router->middlewarePriority = $this->middlewarePriority; foreach ($this->middlewareGroups as $key => $middleware) { $this->router->middlewareGroup($key, $middleware); } foreach ($this->routeMiddleware as $key => $middleware) { $this->router->aliasMiddleware($key, $middleware); } } /** * Register a group of middleware. * * @param string $name * @param array $middleware * @return $this */ public function middlewareGroup($name, array $middleware) { $this->middlewareGroups[$name] = $middleware; return $this; } /** * Register a short-hand name for a middleware. * * @param string $name * @param string $class * @return $this */ public function aliasMiddleware($name, $class) { $this->middleware[$name] = $class; return $this; } ~~~ ### **3.2 处理 HTTP 请求** ~~~ // 处理请求 $response = $kernel->handle( // 创建请求实例 $request = Illuminate\Http\Request::capture() ); ~~~ * 创建请求实例 请求实例 `Illuminate\Http\Request` 的 `capture()` 方法内部通过 **Symfony** 实例创建一个 Laravel 请求实例。这样我们就可以获取到用户请求报文的相关信息 ~~~ /** * Create a new Illuminate HTTP request from server variables. * * @class Illuminate\Http\Request * @return static */ public static function capture() { static::enableHttpMethodParameterOverride(); return static::createFromBase(SymfonyRequest::createFromGlobals()); } /** * Create an Illuminate request from a Symfony instance. * * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php * @param \Symfony\Component\HttpFoundation\Request $request * @return \Illuminate\Http\Request */ public static function createFromBase(SymfonyRequest $request) { if ($request instanceof static) { return $request; } $content = $request->content; $request = (new static)->duplicate( $request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all() ); $request->content = $content; $request->request = $request->getInputSource(); return $request; } ~~~ * 处理请求 请求处理发生在 HTTP 内核 的 `handle()` 方法内。 `Illuminate\Foundation\Http\kernel.php` ~~~ /** * 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; } ~~~ `handle()` 方法接收一个 HTTP 请求,并最终生成一个 HTTP 响应。 继续深入到处理 HTTP 请求的方法**$this->sendRequestThroughRouter($request)**内部。 ~~~ /** * Send the given request through the middleware / router. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ protected function sendRequestThroughRouter($request) { // 将 $request 实例注册到APP 容器供后续使用; $this->app->instance('request', $request); // 清除之前 $request 实例缓存 Facade::clearResolvedInstance('request'); // 启动「引导程序」 $this->bootstrap(); // 发送请求至路由 return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); } ~~~ ## **4. 发送响应** 发送响应由 `Illuminate\Http\Response` 父类 `Symfony\Component\HttpFoundation\Response` 中的 `send()` 方法完成。 ~~~php /** * Sends HTTP headers and content. * * @return $this */ public function send() { // 发送响应头部信息 $this->sendHeaders(); // 发送报文主题 $this->sendContent(); if (\function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { static::closeOutputBuffers(0, true); } return $this; } ~~~ ## **5. 终止程序** 程序终止,完成终止中间件的调用 `Illuminate/Foundation/Http/Kernel.php` ~~~ /** * Call the terminate method on any terminable middleware. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return void */ public function terminate($request, $response) { $this->terminateMiddleware($request, $response); $this->app->terminate(); } /** * Call the terminate method on any terminable middleware. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Response $response * @return void */ protected function terminateMiddleware($request, $response) { $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge( $this->gatherRouteMiddleware($request), $this->middleware ); foreach ($middlewares as $middleware) { if (! is_string($middleware)) { continue; } [$name] = $this->parseMiddleware($middleware); $instance = $this->app->make($name); if (method_exists($instance, 'terminate')) { $instance->terminate($request, $response); } } } ~~~ ***** > 详见:https://learnku.com/articles/10421/depth-mining-of-laravel-life-cycle