一、概述
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);
文章來自:www.haveyb.com/article/166
學習與交流:Laravel技術交流微信群
本作品採用《CC 協議》,轉載必須註明作者和本文連結