◀ 38.

redirectやreturn viewにメッセージを付与する方法

▶
この記事の要点
  • 「保存しました」のような一度だけ表示するメッセージは、セッションのフラッシュデータで渡す
  • リダイレクトするなら return redirect()->route('xxx')->with('message', '保存しました'); が最短
  • return view でその場で表示するだけなら session()->now() か、ビュー変数で渡す
  • session()->flash() の後に return view すると、次の画面でもメッセージが残って二重表示になる
  • Blade 側は @if (session('message')) で存在確認してから表示する

やりたいこと

フォームの送信後に「登録が完了しました」「削除しました」といったメッセージを、次の画面で 1 回だけ表示したい場面はよくあります。Laravel ではこれをフラッシュデータ(次のリクエストまでだけ保持されるセッションの値)で実現します。

どの方法を使うべきかは、コントローラーの最後が redirect なのか return view なのかで変わります。

コントローラーの返し方使う方法メッセージの寿命
redirect / back->with('message', '...')リダイレクト先の 1 リクエストだけ
return viewsession()->now('message', '...') またはビュー変数今回のリクエストだけ
(汎用)session()->flash('message', '...')今回と次のリクエスト

方法 1: redirect にメッセージを付ける(推奨)

POST の処理後はリダイレクトして画面を表示し直すのが定石です(PRG パターン。再読み込みで二重送信されるのを防げます)。リダイレクトレスポンスの with() は、値をフラッシュデータとしてセッションに保存します。

public function store(Request $request)
{
    $user = User::create($request->validated());

    return redirect()
        ->route('users.show', $user)
        ->with('message', 'ユーザーを登録しました');
}

元の画面に戻すなら back() にも同じように付けられます。

return back()->with('message', '更新しました');

// Laravel 9 以降は to_route() でも書ける
return to_route('users.index')->with('message', '削除しました');

方法 2: return view で表示する場合

リダイレクトせず、そのままビューを返してメッセージを表示したい場合は、今回のリクエストだけ有効な session()->now() を使います。

session()->now('message', 'メッセージ');

return view('user', [
    'user' => $user,
]);

セッションを使わず、ビュー変数として渡しても構いません。この場合、Blade 側では session('message') ではなく $message で参照します。

return view('user', [
    'user'    => $user,
    'message' => 'メッセージ',
]);

flash() の直後に return view するとメッセージが二重に出る

次のように session()->flash() の直後に return view しても、今回の画面にはメッセージが表示されます。

session()->flash('message', 'メッセージ');

return view('user', [
    'user' => $user,
]);

ただしフラッシュデータは「次のリクエストまで」保持されるため、ユーザーが次に別のページを開いたときにも同じメッセージがもう一度表示されます。「メッセージが 2 回出る」という不具合の多くはこれが原因です。return view で使うなら now()、リダイレクトするなら with() と使い分けてください。

View(Blade)での表示

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

{{ }} は自動で HTML エスケープされるため、メッセージにユーザー入力を含めても安全です。Laravel 11 以降では @session ディレクティブでも書けます。

@session('message')
    <div class="alert alert-success">{{ $value }}</div>
@endsession

成功とエラーでキーを分ける

キーを分けておくと、見た目を切り替えやすくなります。共通レイアウト(例: layouts/app.blade.php)に一度書けば、全ページで使えます。

@foreach (['success', 'error', 'warning'] as $type)
    @if (session($type))
        <div class="alert alert-{{ $type === 'error' ? 'danger' : $type }}">
            {{ session($type) }}
        </div>
    @endif
@endforeach
return back()->with('error', '在庫が不足しています');

うまく表示されないときの確認ポイント

  • ルートに web ミドルウェアが付いているか: セッションは web ミドルウェアグループで有効になります。routes/api.php のルートではフラッシュメッセージは使えません
  • リダイレクトが 2 回以上連続していないか: リダイレクト先がさらにリダイレクトすると、最初の遷移でフラッシュデータが消費されて表示されません
  • キー名の一致: with('message') と session('msg') のようにキー名がずれていないか
  • バリデーションエラーは別の仕組み: $request->validate() の失敗時は $errors 変数に入ります。自分でエラーを返すなら back()->withErrors([...])->withInput() を使います

セッションの中身を確認したいときは、Blade に一時的に @dump(session()->all()) を書くと、どのキーが入っているかが分かります。

関連

Post Share
子ページ

子ページはありません

同階層のページ
  1. インストールと設定
  2. クイックスタート & チュートリアル(初心者向け)
  3. クイックスタート & チュートリアル(中級者向け)
  4. ルーティング
  5. Bladeテンプレート(ビュー/レイアウト)
  6. コントローラー
  7. マイグレーションとテーブル定義
  8. データベースの設定
  9. Eloquentモデル (ORM)
  10. SQLとクエリビルダー
  11. バリデーション
  12. .envファイルの設定値へのアクセス
  13. 動作環境による分岐処理
  14. configフォルダ配下の設定値へのアクセス
  15. assetヘルパーを利用したpublicフォルダへのアクセス
  16. storageフォルダへのアクセス
  17. アプリケーション名の変更
  18. メンテナンス
  19. ログイン画面(認証システム)の作成
  20. ログインの必須化
  21. ログインユーザー情報の取得
  22. ルートの認証化
  23. 本番サーバーへのデプロイ方法
  24. 多言語化
  25. csrf_field
  26. ファイルのダウンロード
  27. CSVのアップロードおよび読み込み(maatwebsite/excel)
  28. ページタイトルの設定
  29. コマンド一覧
  30. エラー一覧
  31. SQLの実行ログ出力方法
  32. キャッシュのクリア
  33. Selectの結果の最初もしくは最後に任意の値を追加する方法
  34. ajaxでPOST通信する際の注意点
  35. ソーシャルログインの実装
  36. セッション情報の確認
  37. ログイン、ユーザー登録、パスワードリセット後のリダイレクト先の変更方法
  38. redirectやreturn viewにメッセージを付与する方法
  39. クッキー(cookie)の設定と取得
  40. クラスの再読み込み
  41. csrfの有効時間を変更する方法
  42. ViewComposerを用いてviewに共通の値を付与する方法
  43. View::shareを用いて共通の値を各ビューに渡す方法
  44. ミドルウェアを用いた処理の共通化
  45. Middleware内でAuth::check()などを使用する方法
  46. Controller以外でリダイレクトする方法
  47. セッションの値の取得/保存/更新/削除
  48. $requestの値を変更する方法
  49. 常時SSL化
  50. ページング(ページネーション)をする方法
  51. vue.jsとの連携
  52. Vue.jsと連携するSPA実行環境構築
  53. .envの値をvue.jsで参照する方法
  54. vue.jsを本番環境にリリースする方法
  55. could not find driver(Windows, MySQL編)