【Laravel】セッション・フラッシュメッセージの使い方

laravelアイキャッチ Laravel

こんにちは、かつコーチです。

前回は、バリデーションで入力値をチェックする方法を解説しました。

バリデーションを通過して無事にデータが保存できたとき、「登録が完了しました」というメッセージを画面に表示したい場面はとても多いです。

このとき使われるのが、Laravelのセッションフラッシュメッセージという仕組みです。

今回は、この2つの基本的な使い方を、実際の登録処理の流れに沿って解説します。

セッションとは?

ページをまたいでデータを保持する仕組み

セッションとは、あるユーザーがサイトを訪れている間、サーバー側にそのユーザー専用のデータを一時的に保存しておく仕組みです。

HTTP通信は、ページを移動するたびに情報がリセットされる「ステートレス」という性質を持っています。

そのままだと「ログイン中かどうか」「カートに何を入れたか」といった情報を、ページをまたいで覚えておくことができません。

そこで、ユーザーごとに割り振られたIDをブラウザのCookieに保存しておき、そのIDと紐づけてサーバー側にデータを保管するのがセッションの役割です。

Laravelでのセッションの基本操作

Laravelでは、Requestオブジェクトやグローバルヘルパーを使ってセッションを操作できます。

<?php
// 値を保存する
$request->session()->put('user_name', '山田太郎');

// 値を取得する
$name = $request->session()->get('user_name');

// 値を削除する
$request->session()->forget('user_name');

グローバルヘルパー関数の session() を使うと、Requestオブジェクトを受け取っていない場所でも同じ操作ができます。

<?php
session(['user_name' => '山田太郎']);
$name = session('user_name');

どちらの書き方でも中身は同じセッションを操作しているので、コントローラの中では好みや既存コードのスタイルに合わせて選べば問題ありません。

フラッシュメッセージとは?

次の1回だけ表示されるメッセージ

フラッシュメッセージとは、「次のリクエストの間だけ」有効なセッションデータのことです。

通常のセッションデータはユーザーがログアウトしたりデータを消したりするまで残り続けますが、フラッシュメッセージは1回表示されたら自動的に消えます。

「登録が完了しました」「削除しました」のような一度きりの通知にちょうどよい仕組みです。

with()を使った基本パターン

もっともよく使われるのが、リダイレクトと組み合わせる書き方です。

<?php

namespace App\Http\Controllers;

use App\Models\Contact;
use Illuminate\Http\Request;

class ContactController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|max:50',
            'email' => 'required|email',
        ]);

        Contact::create($validated);

        return redirect('/contact')->with('message', '送信が完了しました。');
    }
}

redirect()->with('message', '...') と書くことで、リダイレクト先の画面で1回だけ使えるメッセージをセッションに保存できます。

Blade側では、次のように取り出します。

@if (session('message'))
    <div class="alert alert-success">
        {{ session('message') }}
    </div>
@endif

session('message') でフラッシュメッセージを取得し、表示後は自動的に破棄されます。

もう一度同じページをリロードしても、メッセージは表示されなくなります。

つまずきやすいポイント:flash()とwith()の挙動を勘違いした話

メッセージが消えるタイミングを誤解していた

私が最初にフラッシュメッセージを扱ったとき、「1回表示したら消える」という挙動の細かい違いを理解しておらず、意図しない場面でメッセージが表示され続けるという不具合を出したことがあります。

原因は、session()->put() で直接値を入れてしまっていたことでした。

❌ Before:putで保存してしまい、消えるはずのメッセージが残り続ける

<?php
public function store(Request $request)
{
    Contact::create($request->only(['name', 'email']));

    // put() は通常のセッション保存なので、ずっとデータが残り続ける
    session()->put('message', '送信が完了しました。');

    return redirect('/contact');
}

put() で保存したデータは「次の1回だけ」ではなく、明示的に削除するまでセッションに残り続けます。

そのため、ユーザーがブラウザの戻る・進むを使ったり、別ページから /contact に再びアクセスしたりすると、「送信が完了しました」というメッセージが何度も表示されてしまいました。

✅ After:flash()またはwith()で「次の1回だけ」を明示する

<?php
public function store(Request $request)
{
    Contact::create($request->only(['name', 'email']));

    // flash() は「次のリクエストの間だけ」有効なデータとして保存される
    session()->flash('message', '送信が完了しました。');

    return redirect('/contact');
    // もしくは redirect('/contact')->with('message', '送信が完了しました。');
}

flash()with() を使えば、表示は1回きりで自動的に消えるため、意図しない再表示を防げます。

「通常のデータを保存したいのか、1回きりの通知を出したいのか」を区別してから、put()flash() / with() を使い分けることの大切さを、この一件で学びました。

バリデーションエラーとの関係

前回解説したバリデーションのエラーメッセージも、実は仕組みとしてはフラッシュメッセージと同じです。

$errors 変数は、バリデーションに失敗した直後の1回のリクエストだけ使えるようにフラッシュされたデータです。

「登録完了メッセージ」と「バリデーションエラーメッセージ」、どちらも同じ「次の1回だけ表示する」という設計思想でできている、と理解しておくと仕組み全体がつながって見えてきます。

応用・一歩先の使い方

成功・失敗でメッセージの種類を分ける

実際の開発では、成功メッセージだけでなく、エラーメッセージや警告メッセージも扱うことが多いです。

種類ごとにキーを分けておくと、Blade側での出し分けがしやすくなります。

<?php
public function destroy(Contact $contact)
{
    try {
        $contact->delete();
        return redirect('/contact')->with('success', '削除しました。');
    } catch (\Exception $e) {
        return redirect('/contact')->with('error', '削除に失敗しました。');
    }
}
@if (session('success'))
    <div class="alert alert-success">{{ session('success') }}</div>
@endif

@if (session('error'))
    <div class="alert alert-danger">{{ session('error') }}</div>
@endif

成功時は緑、エラー時は赤、というように見た目も変えておくと、ユーザーは結果を一目で理解できます。

複数のメッセージを配列でまとめて使う

処理内容によっては、メッセージの種類が増えていくこともあります。

そうした場合は、typetext を持つ配列としてまとめてしまうのもひとつの手です。

<?php
return redirect('/contact')->with('flash', [
    'type' => 'success',
    'text' => '送信が完了しました。',
]);
@if (session('flash'))
    <div class="alert alert-{{ session('flash')['type'] }}">
        {{ session('flash')['text'] }}
    </div>
@endif

種類が増えてもBlade側のif文を増やさずに済むため、共通レイアウトでメッセージ表示部分をまとめて管理したいときに役立ちます。

まとめ

この記事のポイント

  • セッションは、ページをまたいでユーザーごとのデータを一時保存する仕組み
  • フラッシュメッセージは「次の1回だけ」表示されるセッションデータ
  • redirect()->with()session()->flash() を使い、put() との違いを意識する
  • バリデーションのエラーメッセージも、仕組みとしてはフラッシュメッセージと同じ
  • 成功・エラーなど種類ごとにキーを分けると、Blade側での出し分けがしやすい

次に読むべき記事

フラッシュメッセージを表示できるようになったら、次はその表示先へどう遷移させるか、リダイレクト処理のパターンを整理していきましょう。

→ 次の記事:リダイレクト処理のパターン集

タイトルとURLをコピーしました