Laravel源碼入門-啓動引導過程(五)$kernel->handle($request)

 

上篇:Laravel源碼入門-啓動引導過程(四)app/Http/Kernel.php

Kernel 做了兩件事,第一個是定義 $bootstraps[],做好了 boot 系統的準備,第二個是定義 各種 middleware,這些都對 $request 進行加工、處理、甄選、判斷,最終爲可以形成正確的、有效的 $response 做準備,都完成後,進行了 index.php 中的 $kernel->handle($request),返回 $response。

仔細分析發現,public/index.php 中 $kernel 在make() 時,真的只是做了準備,真正的載入環境變量(.env)、根據配置載入 Service Providers 等,實際在 $kernel->handle($request) 語句中進行。先貼出加入測試 echo 記錄下的載入過程結果。

// 開始 public/index.php

$app = require_once __DIR__.'/../bootstrap/app.php' 

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

start-->$response = $kernel->handle() 

// 進入 Illuminate/Foundation/Http/Kernel.php

Foundation/Http/Kernel::handle() 
Foundation/Http/Kernel::sendRequestThroughRouter() 
Foundation/Http/Kernel::bootstrap() 

// 進入 Illumniate/Foundation/Application.php

Foundation/Application::bootstrapWith($bootstrapWith) 

Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables

Illuminate\Foundation\Bootstrap\LoadConfiguration
reading config/app.php 

Illuminate\Foundation\Bootstrap\HandleExceptions
Illuminate\Foundation\Bootstrap\RegisterFacades
Illuminate\Foundation\Bootstrap\RegisterProviders
Illuminate\Foundation\Bootstrap\BootProviders

// 回到 public/index.php

end<---$response = $kernel->handle() 

下面具體看一下 Illuminate\Foundation\Http\Kernel.php 的 handle() 及相關代碼片段。

// Illuminate\Foundation\Http\Kernel.php 片段

    /**
     * The bootstrap classes for the application.
     * 引導類,起引導作用的類
     *
     * @var array
     */
    protected $bootstrappers = [
        // 載入服務器環境變量(.env 文件)
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        // 載入配置信息(config 目錄)
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        // 配置如何處理異常
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        // 註冊 Facades
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        // 註冊 Providers
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        // 啓動 Providers
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];

    // 此處省略無關代碼

    /**
     * Handle an incoming HTTP request. 處理請求的 handle()
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function handle($request)
    {
        echo 'Foundation/Http/Kernel::handle() <br />';
        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);
        }

        event(new Events\RequestHandled($request, $response));

        return $response;
    }

    /**
     * Send the given request through the middleware / router.
     * 將請求發送至中間件、路由處理。
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function sendRequestThroughRouter($request)
    {
        echo 'Foundation/Http/Kernel::sendRequestThroughRouter() <br />';

        $this->app->instance('request', $request);

        Facade::clearResolvedInstance('request');

        // Kernel 要啓動引導
        $this->bootstrap();

        return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                    ->then($this->dispatchToRouter());
    }

    /**
     * Bootstrap the application for HTTP requests.
     * 啓動引導(requests 驅動)
     *
     * @return void
     */
    public function bootstrap()
    {
        echo 'Foundation/Http/Kernel::bootstrap() <br />';

        if (! $this->app->hasBeenBootstrapped()) {
            // 使用 Application 的 bootstrapWith()方法啓動引導
            // 參數是 Kernel 中的 bootstrapers[]。
            $this->app->bootstrapWith($this->bootstrappers());
        }
    }

=== 總結 ===

如先期描述的 handle() 通過 sendRequestThroughtRouter($request) 處理請求,返回 $response,途中進行了 啓動引導,$this->bootstrap(),進一步調用 Application 的 bootstrapWith(),將自己定義的 bootstrapper[] 傳入,這個 bootstrappers[] 如前定義,包括了載入服務器環境變量、配置信息、服務提供者、異常處理等。一切結束後,沒有拋出異常的話,返回 public/index.php,正如開始的 echo 記錄一樣。

附:Application 中 bootstrapWith() 代碼

下篇:Laravel源碼入門-啓動引導過程(六)LoadEnvironmentVariables

// Illuminate\Foundation\Application.php 代碼片段

    /**
     * Run the given array of bootstrap classes.
     *
     * @param  array  $bootstrappers
     * @return void
     */
    public function bootstrapWith(array $bootstrappers)
    {
        echo 'Foundation/Application::bootstrapWith($bootstrapWith) <br />';
        $this->hasBeenBootstrapped = true;

        foreach ($bootstrappers as $bootstrapper) {
            echo $bootstrapper . '<br />';
            
            $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);

            // 解析每個 $bootstrapper,由調用他們自身的 bootstrap(),引導。
            $this->make($bootstrapper)->bootstrap($this);

            $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章