こんにちは、かつコーチです。
前回は、バリデーションで入力値をチェックする方法を解説しました。
バリデーションを通過して無事にデータが保存できたとき、「登録が完了しました」というメッセージを画面に表示したい場面はとても多いです。
このとき使われるのが、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
成功時は緑、エラー時は赤、というように見た目も変えておくと、ユーザーは結果を一目で理解できます。
複数のメッセージを配列でまとめて使う
処理内容によっては、メッセージの種類が増えていくこともあります。
そうした場合は、type と text を持つ配列としてまとめてしまうのもひとつの手です。
<?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側での出し分けがしやすい
次に読むべき記事
フラッシュメッセージを表示できるようになったら、次はその表示先へどう遷移させるか、リダイレクト処理のパターンを整理していきましょう。
→ 次の記事:リダイレクト処理のパターン集