laravelライフサイクル-リクエスト発生からレスポンスを返すまで

laravelのリクエストがあってかレスポンスを返すまでの一つのライフサイクルの流れを本日はお伝えします。

このライフサイクルがわからないとLaravelに何か追加したいときに、

どこをいじったら良いのか?という部分がわかりません。

なるべく早い段階で理解してください。

ライフサイクルとは?

そもそもライフサイクルとは何か・・というと、

ご自身のスマートフォンやPCでサイトにアクセスした時にリクエストが発生してサーバーに問い合わせをし、その問い合わせの返答が返ってくるまでのことを言います。

下記にライフサイクルの図を用意しておきましたので、ご確認ください。

この図に沿ってそれぞれどのようなことをしているのかをお伝えしていきます。

エントリポイント

送信されたhttpリクエストは、エントリポイントであるpublic/index.phpに入り、処理します。Laravelアプリケーションに入ってくる全httpリクエストはここで処理します。

このクラスの構造はシンプルなので、下記コードをもって説明していきます。

`<?php

define('LARAVEL_START', microtime(true));
require __DIR__.'/../vendor/autoload.php';
→①

$app = require_once __DIR__.'/../bootstrap/app.php';
→②

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

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

$response->send();

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

①,オートローダーの読み込み

まず、オートローダーの読み込みを行なっています。
オートローダとは、外部にあるphpファイルを自動的に読み込む仕組みです。
*後日詳しく記事化します。

②,フレームワークのセットアップ

bootstrap/app.phpファイルからLaravelアプリケーションのインスタンスを取得します。下記がファイル内容です。

`<?php

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
→1

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);
→2

$app->singleton(
    Illuminate\Contracts\Console\Kernel::class,
    App\Console\Kernel::class
);
→3
$app->singleton(
    Illuminate\Contracts\Debug\ExceptionHandler::class,
    App\Exceptions\Handler::class
);
→4

return $app;

1にて、IlluminateFoundationApplicationのインスタンを返し、Laravel アプリケーションの中核となるサービスコンテナ を作成しています。

2,3,4にて作成したサービスコンテナ を使って、サービスコンテナにてインスタンスを生成しています。

③,httpカーネルの作成

ここで一度一つ前のコードを見ていただいて、$app->make()でhttpカーネルのインスタンスを作成しているのがわかると思います。このインスタンスにて、handleメソッドを用いて、リクエストを引数に用いて、最終的にユーザーに返すことになるレスポンスを作成しています。作成したレスポンスは、sendメソッドで送り、terminateメソッドで終了します。

複雑に見えるLaravelフレームワークですがこの部分をみることで、大きな全体の流れを理解することができます。

httpカーネル/Consoleカーネル

先ほどのコードから見てわかるようにカーネルは、起動時に二つ作成されています。

ここでは主に、httpカーネルについてお話ししていきます。

*ConsoleカーネルではLaravelで使用することになるコマンド(php artisan ***)のセットアップをしていきます。

httpカーネルでは、リクエストの実行前に必要な$bootstrappers配列を定義しています。サービスプロバイダ,Env,config, Facadeなんかもここで定義しています。

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,
    ];

続いて、先ほど使用したレスポンスを作成したhandleメソッドを見てみましょう。

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 Events\RequestHandled($request, $response)
        );

        return $response;
    }

①の部分にてリクエストをルータに渡しています。また、try,catchブロックがあるのがわかると思いますが、ここでは、フレームワークでエラーが起こった場合にはここのブロックで処理されます。

①の部分でルータに渡すメソッドを深く見てみましょう。
$this->dispatchToRouter()の部分でルータにhttpリクエストを渡しています、

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());
    }

Router

ルータでは、定義されたルートの中からRequestにマッチするルートを探していきます。
マッチしたルートに応じて、そこで定義されているコントローラーにリクエストを渡していきます。

Contorller

渡されたhttpリクエストに対応する処理を行い、処理が終わった段階でレスポンスを返します。データベースの処理やビジネスロジックの処理はここでおこなれます。

view

View ヘルパー関数を用いてviewを返却する場合は、viewがレスポンスとして返却されます。

class SampleController extends controller{
	public function sample(){
    return view(‘welcome’);
  }
}

まとめ

Laravel フレームワークは一見するとすごい複雑・・と思ってしまいがちですが、このライフサイクルを理解することで、少しでも日々の問題解決につながれば幸いです。

サービスコンテナ 、サービスプロバイダなどの記事もできれば一緒に読んで理解を深めてくださいね。 

1 COMMENT

コメントを残す