Laravelのold()関数でフォームに入力値を復元する方法を完全解説!バリデーションエラー後も入力が消えない仕組み
生徒
「フォームで入力ミスがあってエラーが出ると、入力した内容が全部消えてしまうんですが、これってどうにかなりますか?」
先生
「Laravelにはold()という関数があって、バリデーションエラーが起きたときに入力した値をフォームに自動で戻してくれます。」
生徒
「それは便利ですね!使い方を教えてください。」
先生
「仕組みから順番に説明するので、一緒に見ていきましょう。」
1. old()関数とは?フォームの入力値復元の仕組み
Laravelのold()関数は、フォームに入力された値を画面に戻すためのヘルパー関数です。
ヘルパー関数とは、よく使う処理を短く書けるようにLaravelがあらかじめ用意してくれている便利な関数のことです。
たとえばユーザー登録フォームで名前やメールアドレスを入力したあと、 何か入力ミスがあってエラーになったとします。 普通ならエラーページに移動した瞬間に入力した内容がすべて消えてしまい、 もう一度最初から入力し直さなければなりません。 これはユーザーにとってとても不便で、ストレスになります。
old()関数を使うと、エラーが起きてもフォームに元の入力内容が自動的に復元されます。
書類の下書きを保存しておいて、間違えたときでもそこから再入力できるイメージです。
これはUX(ユーザーエクスペリエンス)、つまりウェブサービスを使う人の体験を大きく向上させる重要な機能です。
この仕組みの裏側ではセッションと呼ばれる技術が使われています。
セッションとは、ウェブサーバーが一時的にデータを記憶しておく仕組みのことです。
Laravelはバリデーションエラーが発生したとき、入力値をセッションに一時保存し、
リダイレクト先のページでold()を通じてその値を取り出す、という流れで動作しています。
2. バリデーションとリダイレクトの流れを理解しよう
old()関数を理解するうえで、バリデーションとリダイレクトの流れを把握しておくことが大切です。
バリデーションとは、フォームに入力されたデータが正しい形式かどうかをチェックする処理のことです。 たとえば「メールアドレスの形式になっているか」「必須項目が空ではないか」などを確認します。 リダイレクトとは、ユーザーを別のページへ自動的に移動させることです。
Laravelでバリデーションに失敗したとき、フレームワークは自動的に以下の処理を行います。
- 入力値をセッションに一時保存する(フラッシュデータとして保存)
- エラーメッセージをセッションに保存する
- 直前のページ(フォームページ)にリダイレクトする
フラッシュデータとは、次のリクエスト(ページ読み込み)のときだけ使えて、
その後は自動的に消えるセッションデータのことです。
old()関数はこのフラッシュデータから値を取り出して表示しています。
コントローラーでバリデーションを行う基本的なコードは以下のようになります。
// app/Http/Controllers/UserController.php
public function store(Request $request)
{
// バリデーションの実行
// 失敗した場合はLaravelが自動的に元のページへリダイレクトし入力値を保存する
$request->validate([
'name' => 'required|max:50',
'email' => 'required|email',
'body' => 'required',
]);
// バリデーションを通過した場合の処理(例:データベースへの保存)
User::create($request->all());
return redirect()->route('users.index');
}
validate()メソッドがバリデーション失敗を検知すると、
入力値をセッションに保存しながら自動でリダイレクトしてくれます。
この動作があるからこそ、old()関数がフォームページで値を復元できるのです。
3. old()関数の基本的な使い方
old()関数はBladeテンプレート(LaravelでHTMLを作るためのファイル)の中で使います。
使い方はとてもシンプルで、old('フォームの入力欄の名前')と書くだけです。
以下は名前とメールアドレスを入力するシンプルなフォームの例です。
<!-- resources/views/users/create.blade.php -->
<form action="{{ route('users.store') }}" method="POST">
@csrf
<!-- 名前の入力欄 -->
<div class="mb-3">
<label for="name" class="form-label">お名前</label>
<input
type="text"
id="name"
name="name"
class="form-control"
value="{{ old('name') }}"
>
</div>
<!-- メールアドレスの入力欄 -->
<div class="mb-3">
<label for="email" class="form-label">メールアドレス</label>
<input
type="email"
id="email"
name="email"
class="form-control"
value="{{ old('email') }}"
>
</div>
<button type="submit" class="btn btn-primary">送信する</button>
</form>
ポイントはvalue="{{ old('name') }}"の部分です。
value属性とは、入力欄にあらかじめ表示しておく値を指定するHTMLの属性です。
ここにold('name')を入れることで、バリデーションエラーのあとに
入力欄へ元の値が自動的に入った状態でページが表示されます。
初めてフォームを表示するとき(まだ何も送信していないとき)は、
セッションに保存された値がないためold()は空の文字列を返します。
そのため入力欄は空のまま表示され、通常通り使えます。
4. デフォルト値を設定する方法
old()関数は第二引数にデフォルト値を指定することができます。
デフォルト値とは、セッションに保存された値がない場合(初回表示時など)に代わりに表示する値のことです。
たとえば編集フォームのように、データベースからすでに登録済みの値を初期表示したい場合に活用できます。
<!-- 編集フォームの例($userはコントローラーから渡されたデータ) -->
<div class="mb-3">
<label for="name" class="form-label">お名前</label>
<input
type="text"
id="name"
name="name"
class="form-control"
value="{{ old('name', $user->name) }}"
>
</div>
<div class="mb-3">
<label for="email" class="form-label">メールアドレス</label>
<input
type="email"
id="email"
name="email"
class="form-control"
value="{{ old('email', $user->email) }}"
>
</div>
old('name', $user->name)と書くと、以下のように動作します。
- セッションに値がある場合(バリデーションエラー後) → セッションの値を表示
- セッションに値がない場合(初回表示) →
$user->nameの値を表示
これにより新規作成フォームと編集フォームのどちらでも、同じ書き方で入力値の復元と初期値の表示を両立できます。 コードの重複を減らし、シンプルに管理できる点が大きなメリットです。
5. テキストエリアやセレクトボックスでの使い方
old()関数はinputタグだけでなく、
テキストエリアやセレクトボックスでも使えます。
テキストエリアとは複数行の文章を入力できる欄で、セレクトボックスとはドロップダウン形式で選択肢を選べる入力欄のことです。
それぞれ書き方が少し異なるので確認しておきましょう。
<!-- テキストエリアでのold()の使い方 -->
<!-- valueではなく、タグの内側にold()を書く -->
<div class="mb-3">
<label for="body" class="form-label">お問い合わせ内容</label>
<textarea
id="body"
name="body"
class="form-control"
rows="5"
>{{ old('body') }}</textarea>
</div>
<!-- セレクトボックスでのold()の使い方 -->
<!-- selected属性をold()と比較して付ける -->
<div class="mb-3">
<label for="category" class="form-label">カテゴリ</label>
<select id="category" name="category" class="form-select">
<option value="">選択してください</option>
<option value="news" {{ old('category') == 'news' ? 'selected' : '' }}>ニュース</option>
<option value="product" {{ old('category') == 'product' ? 'selected' : '' }}>製品情報</option>
<option value="support" {{ old('category') == 'support' ? 'selected' : '' }}>サポート</option>
</select>
</div>
テキストエリアはvalue属性がないため、開始タグと終了タグの間に{{ old('body') }}を書きます。
スペースや改行が入ると表示に影響するため、の直前に書くのがポイントです。
セレクトボックスは、old('category')で取得した値と
各optionタグのvalue属性を比較して、
一致した選択肢にselected属性を付けることで選択状態を復元します。
?と:を使った書き方は三項演算子といって、
条件によって返す値を一行で切り替えるPHPの書き方です。
6. チェックボックスやラジオボタンでの使い方
チェックボックスやラジオボタンでもold()を使って選択状態を復元できます。
これらはchecked属性の有無によって選択状態が決まります。
チェックボックスの場合、送信されなかった(チェックされていない)ときは値がリクエストに含まれないため、
old()の代わりにold('agree') == 'on'のような比較が必要になります。
<!-- チェックボックスでの復元 -->
<div class="mb-3 form-check">
<input
type="checkbox"
id="agree"
name="agree"
class="form-check-input"
value="1"
{{ old('agree') ? 'checked' : '' }}
>
<label for="agree" class="form-check-label">利用規約に同意する</label>
</div>
<!-- ラジオボタンでの復元 -->
<div class="mb-3">
<div class="form-check">
<input
type="radio"
id="gender_male"
name="gender"
class="form-check-input"
value="male"
{{ old('gender') == 'male' ? 'checked' : '' }}
>
<label for="gender_male" class="form-check-label">男性</label>
</div>
<div class="form-check">
<input
type="radio"
id="gender_female"
name="gender"
class="form-check-input"
value="female"
{{ old('gender') == 'female' ? 'checked' : '' }}
>
<label for="gender_female" class="form-check-label">女性</label>
</div>
</div>
チェックボックスはold('agree')が値を持っていればcheckedを付け、
ラジオボタンはold('gender') == 'male'のように値を比較して対応する選択肢にcheckedを付けます。
この書き方を覚えておくと、複雑なフォームでも入力値を正確に復元できます。
ウェブアプリケーションでフォームを作る場合、入力値の復元はユーザーの使いやすさに直結する重要な要素です。
特に項目数が多いフォームでは、エラー後に全部入力し直すのは非常に手間がかかります。
old()関数を使いこなすことで、ユーザーにやさしいフォームを作れるようになります。
7. バリデーションエラーメッセージとold()を組み合わせる
実際のフォームでは、old()による入力値の復元とあわせて、
バリデーションエラーメッセージの表示も行うことが一般的です。
エラーメッセージとは、入力が正しくなかったときに「この項目は必須です」などと表示する案内文のことです。
Laravelのバリデーションが失敗すると、エラー情報が$errorsという変数に格納されます。
Bladeテンプレートでは@errorディレクティブを使うと、
特定の入力欄にエラーがあるときだけメッセージを表示できます。
ディレクティブとは、Bladeテンプレート専用の特別な命令文のことです。
<!-- old()とエラーメッセージを組み合わせた完成形の例 -->
<div class="mb-3">
<label for="name" class="form-label">お名前 <span class="text-danger">*</span></label>
<input
type="text"
id="name"
name="name"
class="form-control {{ $errors->has('name') ? 'is-invalid' : '' }}"
value="{{ old('name') }}"
>
@error('name')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
<div class="mb-3">
<label for="email" class="form-label">メールアドレス <span class="text-danger">*</span></label>
<input
type="email"
id="email"
name="email"
class="form-control {{ $errors->has('email') ? 'is-invalid' : '' }}"
value="{{ old('email') }}"
>
@error('email')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
$errors->has('name')はその入力欄にエラーがあるかどうかを調べます。
エラーがある場合はis-invalidというBootstrapのクラスを追加することで、
入力欄が赤くハイライトされます。
@error('name')と@enderrorの間に書いた{{ $message }}が、
エラーメッセージの本文として表示されます。
このようにold()とエラー表示を組み合わせることで、
ユーザーが「どの入力欄が間違っているのか」「どんな間違いなのか」をひと目で把握でき、
修正がスムーズに行えるフォームが完成します。
Laravelを使った開発では、このパターンが標準的なフォームの作り方として広く使われています。