Laravel 底层是如何处理 HTTP 请求的?
基于 Laravel 框架構建的 Web 應用處理 HTTP 請求的流程也是如此。所有 HTTP 請求都會被轉發到單入口文件?public/index.php,處理 HTTP 請求的核心代碼如下(忽略 HTTP 請求處理之外的代碼):
$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') ); // 綁定處理 HTTP 請求的接口實現到服務容器 $app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class );// 從服務容器中解析處理 HTTP 請求的 Kernel 實例 $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);// 處理 HTTP 請求的核心代碼 $response = $kernel->handle( $request = Illuminate\Http\Request::capture() );// 發送響應 $response->send();// 終止程序,做一些善后及清理工作 $kernel->terminate($request, $response);
?
在上面這段程序中,首先會創建一個?Application?實例,作為全局的服務容器,然后將處理請求的核心類 Kernel 實現實例綁定到該容器中,以便后續通過它處理 HTTP 請求。我們通過服務器捕獲請求并將其傳遞給 Kernel 實例進行處理,處理結果是準備好的響應實例,調用該響應實例的?send()?方法即可將其發送給發起請求的客戶端。最后,我們執行 Kernel 實例上的?terminate()?終止程序,退出腳本。
以上就是 Laravel 框架處理 HTTP 請求的一般流程,所有核心邏輯都位于?$kernel->handle()?方法調用中。下面我們就來一探究竟。
?
服務容器
Laravel 框架提供了一個功能強大的服務容器,用于管理類之間的依賴關系,關于其底層原理還可以參考學徒到工匠系列中的介紹,這里我們就不深入展開了。服務容器封裝了綁定到某個接口的對應實現類的實例化過程,你可以在需要對應實現實例的時候通過接口從容器中獲取。
在上面的代碼中,$app?對應的就是服務容器實例,并且在我們獲取到該實例后就注冊了 Kernel 接口及其實現類到容器中:
$app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class );singleton 方法會以單例方式在服務容器中將 App\Http\Kernel 實例綁定到 Illuminate\Contracts\Http\Kernel 接口,后續我們要獲取 App\Http\Kernel 實例,就可以通過 Illuminate\Contracts\Http\Kernel 接口從服務容器中獲取,獲取方法是 $app->make():$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
?
回到 Kernel
下面我們就正式進入?$kernel->handle()?方法內部看看 HTTP 請求是被如何處理的。打開?Illuminate\Foundation\Http\Kernel?(App\Http\Kernel?的父類),查看?handle?方法,可以看到核心處理邏輯通過?sendRequestThroughRouter?方法實現:
protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request);Facade::clearResolvedInstance('request');$this->bootstrap();return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }在發送請求到路由之前,先調用 bootstrap() 方法運用應用的啟動類:protected $bootstrappers = [ \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ];
?
這些個啟動類在路由解析之前執行,相當于對整個應用進行初始化。通過類名就能窺探出對應的操作意圖,分別是加載環境變量和全局配置、配置異常處理邏輯、注冊門面和服務提供者(根據?config/app.php?中的?providers?和?alias配置值)、以及執行所有已注冊服務提供者的?boot?方法,具體的實現邏輯我這里就不一一展開的,你可以自己去看下。
然后就是真正的 HTTP 請求處理了:
return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter());
?
Laravel 框架以管道模式來處理 HTTP 請求,首先通過全局中間件對請求進行處理,如果返回 false 直接退出,不會做路由解析處理。
全局中間件都校驗通過才會將請求分發到路由器進行處理,路由器會將請求 URL 路徑與應用注冊的所有路由進行匹配,如果有匹配的路由,則先收集該路由所分配的所有路由中間件,通過這些路由中間件對請求進行過濾,所有路由中間件校驗通過才會運行對應的匿名函數或控制器方法,執行相應的請求處理邏輯,最后準備好待發送給客戶端的響應。
終止 Kernel
響應準備就緒后,就會通過?$response->send()?發送給發起請求的客戶端,之后還要運行?$kernel->terminate()?做一些善后清理工作,并最終退出腳本。這些善后清理工作主要包括運行終止中間件,以及注冊到服務容器的一些終止回調:
public function terminate($request, $response) { $this->terminateMiddleware($request, $response);$this->app->terminate(); }
?
轉載于:https://www.cnblogs.com/mo3408/p/10979279.html
總結
以上是生活随笔為你收集整理的Laravel 底层是如何处理 HTTP 请求的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js 递归总结
- 下一篇: js 动态加载select触发事件