2024-06-18

Laravelのflashの仕組み

Laravelの RedirectResponse::with() のflashが何をやっているのかコードリーディングメモ。


RedirectResponse::with()Illuminate\Session\Store::flash() を呼び出します。

public function with($key, $value = null)
{
    $key = is_array($key) ? $key : [$key => $value];

    foreach ($key as $k => $v) {
        $this->session->flash($k, $v);
    }

    return $this;
}

https://github.com/laravel/framework/blob/v11.0.7/src/Illuminate/Http/RedirectResponse.php#L35-L51

flash() では以下のようなことをやっています。

public function flash(string $key, $value = true)
{
    $this->put($key, $value);

    $this->push('_flash.new', $key);

    $this->removeFromOldFlashData([$key]);
}

https://github.com/laravel/framework/blob/v11.0.7/src/Illuminate/Session/Store.php#L443-L450

例えば with(['message' => 'OK']) という呼び出しをした場合、

key value
message OK
_flash.new [message]
_flash.old []

という状態になります。

この Illuminate\Session\StoreIlluminate\Session\Middleware\StartSession::saveSession()save() メソッドが呼ばれます。 https://github.com/laravel/framework/blob/v11.0.7/src/Illuminate/Session/Middleware/StartSession.php#L245

save() では以下の処理を行ってます。

public function save()
{
    $this->ageFlashData();

    $this->prepareErrorBagForSerialization();

    $this->handler->write($this->getId(), $this->prepareForStorage(
        $this->serialization === 'json' ? json_encode($this->attributes) : serialize($this->attributes)
    ));

    $this->started = false;
}

https://github.com/laravel/framework/blob/v11.0.7/src/Illuminate/Session/Store.php#L166-L177

public function ageFlashData()
{
    $this->forget($this->get('_flash.old', []));

    $this->put('_flash.old', $this->get('_flash.new', []));

    $this->put('_flash.new', []);
}

https://github.com/laravel/framework/blob/v11.0.7/src/Illuminate/Session/Store.php#L218-L225

さきほどの例だと以下のように _flash.new から _flash.old に移動していることがわかります。

key value
message OK
_flash.new []
_flash.old [message]

この状態でセッションストレージに保存され、次にリクエストしたとき=リダイレクトGETしたときにmessageの値を取得できます。

次にリクエストしたときも同様のミドルウェアの処理で ageFlashData() が呼ばれます。もしflashの処理やセッションの設定をしていない場合は以下の状態になります。 _flash.old に格納されていたmessageのキーが削除され、 _flash.new_flash.old に移動して空になっています。

key value
_flash.new []
_flash.old []

このようにして、リダイレクトGETした1回のみ有効なセッションデータを作り出しています。

このエントリーをはてなブックマークに追加