1、從入口文件開始分析
Laravel 的入口文件是 /public/index.php。
在 index.php 中,處理請求的代碼是:
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
Laravel 請求類 Request 剖析 說明了 $request 是如何獲得的,下面將着重分析 handle 方法是如何處理請求的。
2、分析 $kernel 調用的 handle () 方法
它調用了 handle () 方法,在 App\Http\Kernel.php 中並沒有 handle () 方法,因此它調用的其實是它的父類中的 handle 方法。
它的父類 handle () 方法是這樣:
public function handle($request)
{
try {
// 啓用對方法請求參數的支持
$request->enableHttpMethodParameterOverride();
// 通過中間件/路由器發送給定的請求
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
...
}
$this->app['events']->dispatch(
new RequestHandled($request, $response)
);
return $response;
}
可以看到,解析請求獲得響應的關鍵就在這一行代碼:
$response = $this->sendRequestThroughRouter($request);
這個方法是這樣的:
protected function sendRequestThroughRouter($request)
{
// 將現有實例註冊爲容器中的共享實例
$this->app->instance('request', $request);
// 清除已解析的外觀實例
Facade::clearResolvedInstance('request');
// 在發送請求到路由之前,調用 bootstrap() 方法運用應用的啓動類
$this->bootstrap();
// 以管道模式來處理 HTTP 請求
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
注:
new Pipeline($this->app):
// 創建 Illuminate\Routing\Pipeline 實例,並將應用實例 $this->app 賦值給 Illuminate\Pipeline\Pipeline 的 container 容器屬性
send($request):
// 設置通過管道發送的對象,把request 賦值給 Illuminate\Pipeline\Pipeline 的 passable屬性
through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
// 確定是否已爲應用程序禁用中間件
then($this->dispatchToRouter())
// 獲取路由調度程序回調,使用最終回調運行管道