今回は、またしても新規のLaravelのバージョン対しての私のキャッチアップの話です。もちろん、存在は知っていたのですが、最近まで使用する機会がありませんでした。ブレードで使われる@errorの話なのですが、調べたら登場したのはなんとLaravelバージョン5.8、現在のバージョンが8.xなので遠い昔のように思えます。しかし、5.8がリリースされたのはつい去年のことです。Laravelのバージョン形態が変わってから、どんどん更新が早まっていくように感じられます。

@if vs @error

まず、バリデーションエラー表示において、どう@ifから@errorへ進化したかを比較してみます。

@ifを使用すると、

<label for="title">投稿のタイトル</label>

<input id="title" type="text" class="@if ($errors->has('title') is-invalid @endif">

@if ($errors->has('title')
    <div class="alert alert-danger">{{ $errors->first('title') }}</div>
@endif

これが、@errorを使用すると、

<label for="title">投稿のタイトル</label>

<input id="title" type="text" class="@error('title') is-invalid @enderror">

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

両者とも意味は同じですが、@errorの方がすっきりして意味がわかりやすいですね。

配列の入力があるフォームで@error

さて、先の例と違って、以下のような配列フォームではどう@errorを使うことができるでしょう?

まず、エラー表示のもととなるコントローラのバリデーションは、

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class FormController extends Controller
{
    public function create()
    {
    	return view('form.create');
    }

    public function store(Request $request)
    {
    	$rules = [
            'name.*'  => 'nullable',
            'price.*' => 'nullable|required_with:name.*|integer|gt:0',
    	];

        $messages = [
            'price.*.required_with' => '入力してください',
            'price.*.integer'       => '整数で入力してください',
            'price.*.gt'            => '0超の整数で入力してください',
        ];

    	$validated = $request->validate($rules, $messages);

        // DBに保存...
   }
...

配列だから、name.*のように、項目名に*が使用されていることに注意してください。
nullableは、空(null)の入力でもOKという意味です。

使用されるブレードは、

@extends('layouts.app')

@section('content')
<div class="container">
  <div class="row justify-content-center">
    <div class="col-md-8">
      <div class="card">
        <div class="card-header">出費</div>

        <div class="card-body">
          <form method="POST" action="{{ route('form.store') }}">
            @csrf

            <div class="table-responsive">
              <table class="table table-bordered table-hover table-sm">
              <thead>
                <tr>
                <th class="">アイテム名</th>
                <th class="">金額</th>
                </tr>
              </thead>
              <tbody>
                @for($i = 0; $i < 5; $i++)
                  <tr>
                    <td>
                      <input type="text" class="form-control @error('name.'.$i) is-invalid @enderror" name="name[]" value="{{ old('name.'.$i) }}">
                      @error('name.'.$i)
                        <span class="invalid-feedback" role="alert">
                          <strong>{{ $message }}</strong>
                        </span>
                      @enderror
                    </td>
                    <td>
                      <input type="text" class="form-control @error('price.'.$i) is-invalid @enderror" name="price[]" value="{{ old('price.'.$i) }}">
                      @error('price.'.$i)
                        <span class="invalid-feedback" role="alert">
                          <strong>{{ $message }}</strong>
                        </span>
                      @enderror
                    </td>
                  </tr>
                @endfor
              </tbody>
              </table>
            </div>

            <div class="row justify-content-center">
              <button type="submit" class="btn btn-primary">
                  保存
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</div>
@endsection

@error('price.'.$i)と、price1でなくprice.1となっていることに注意してください。Laravelでは、price.1は指定の配列値で、price[1]と同じことです。同様に、old()でもold('price.'.$i)price.1となっています。

By khino