Laravel - Request Lifecycle

簡單整理一下 Laravel request 的生命週期

Auto loader

首先,在 Laravel application 所有 request 優先訪問 public/index.php

其實開啟 public/index.php ,先略過多數註解,其實程式碼也就幾行:

<?php
//Laravel - A PHP Framework For Web Artisans
define('LARAVEL_START', microtime(true));

//Register The Auto Loader
require __DIR__.'/../vendor/autoload.php';

//Turn On The Lights
$app = require_once __DIR__.'/../bootstrap/app.php';

//Run The Application
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);

在 public/index.php 這隻檔案,前面會載入 Compoer autoloader

接著會收到由 bootstrap/app.php 腳本所執行初始化一些實例,

這時,Laravel 會建構第一個 service container 實例

Kernels

接著, request 被傳送到 HTTP Kernel 或 console kernel (由 Request 的類型而定)

通常 request 主要都會分配到 HTTP Kernel :

app/Http/Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];

    /**
     * The priority-sorted list of middleware.
     *
     * This forces non-global middleware to always be in the given order.
     *
     * @var array
     */
    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\Authenticate::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];
}

在 HTTP Kernel 會先載入 Illuminate\Foundation\Http\Kernel 類別,這個類別定義了 bootstrappers 陣列,會優先執行

<?php
...
    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,
    ];

bootstrappers 主要載入service providers,錯誤處理(error handling),logging,取得環境變數以及其他需要任務等等。

在這當中,RegisterFacades ,RegisterProviders 這兩個 class 主要就是將 service providers 注入 IoC 容器。

service provider 主要都在 config/app.php 設定,主要檔案都放在 app/Providers ,這也是整個 Laravel 啟動過程最重要的核心。

此外, HTTP Kenel 包括了一些 HTTP middleware,讓所有的 request 都會通過這些 middleware ,這些 middleware 會讀取及寫入 HTTP session 中、確認目前是否處於 maintenance mode 階段、驗證CSRF Token 等等,最後會由 HTTP Kernel 中的 handle 方法將的的 Request return 一個 Response,並且導向 router。

Dispatch Request

當 Kernel 處理返回一個 Response後,就會接續開始處理router 中的 Request 調度。

首先,router 會優先執行指定的 middleware,接著,會根據 router 設定來決定要調度請求到 route 或者 controller,通常,最後會在 Controller 將結果返回一個 view ,將結果返回 web server 到使用者的瀏覽器。

因此,HTTP requests 在 HTTP Kernel 經過了相當多道流程,最後才返回 HTTP responses。

整體來說,Laravel 請求的生命週期,主要就是先創建出第一個實例後,接著主要就是開始註冊 service provider,最後就可以開始處理請求。