[TOC]

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
- PHP
- PHP 核心架構
- PHP 生命周期
- PHP-FPM 詳解
- PHP-FPM 配置優化
- PHP 命名空間和自動加載
- PHP 運行模式
- PHP 的 Buffer(緩沖區)
- php.ini 配置文件參數優化
- 常見面試題
- 常用函數
- 幾種排序算法
- PHP - 框架
- Laravel
- Laravel 生命周期
- ThinkPHP
- MySQL
- 常見問題
- MySQL 索引
- 事務
- 鎖機制
- Explain 使用分析
- MySQL 高性能優化規范
- UNION 與 UNION ALL
- MySQL報錯:sql_mode=only_full_group_by
- MySQL 默認的 sql_mode 詳解
- 正則表達式
- Redis
- Redis 知識
- 持久化
- 主從復制、哨兵、集群
- Redis 緩存擊穿、穿透、雪崩
- Redis 分布式鎖
- RedisBloom
- 網絡
- 計算機網絡模型
- TCP
- UDP
- HTTP
- HTTPS
- WebSocket
- 常見幾種網絡攻擊方式
- Nginx
- 狀態碼
- 配置文件
- Nginx 代理+負載均衡
- Nginx 緩存
- Nginx 優化
- Nginx 配置 SSL 證書
- Linux
- 常用命令
- Vim 常用操作命令
- Supervisor 進程管理
- CentOS與Ubuntu系統區別
- Java
- 消息隊列
- 運維
- RAID 磁盤陣列
- 邏輯分區管理 LVM
- 業務
- 標準通信接口設計
- 業務邏輯開發套路的三板斧
- 微信小程序登錄流程
- 7種Web實時消息推送方案
- 用戶簽到
- 用戶注冊-短信驗證碼
- SQLServer 刪除同一天用戶重復簽到
- 軟件研發完整流程
- 前端
- Redux
- 其他
- 百度云盤大文件下載
- 日常報錯記錄
- GIT
- SSL certificate problem: unable to get local issuer certificate
- NPM
- reason: connect ECONNREFUSED 127.0.0.1:31181
- SVN
- SVN客戶端無法連接SVN服務器,主機積極拒絕
- Python
- 基礎
- pyecharts圖表
- 對象
- 數據庫
- PySpark
- 多線程
- 正則
- Hadoop
- 概述
- HDFS