前回の例はメールアドレス1つの入力でしたが、今度はちょっと複雑にして複数のメールアドレスを入力する配列入力の話です。
入力画面
画面はこんな感じです。
そして、その画面のブレードはこんなです。前回で定義したx-inputのコンポーネントを使用しています。
<x-layout> <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"> <x-form action="{{ route('register') }}"> @for($i=1;$i <=3;$i++) <div class="row mb-3"> <x-label name="email{{ $i }}">メールアドレス {{ $i }}</x-label> <div class="col-md-6"> <x-input id="email{{ $i }}" type="email" name="emails[{{ $i }}]" /> </div> </div> @endfor <div class="row mb-0"> <div class="col-md-6 offset-md-4"> <x-button type="submit" class="m-2" level="primary">登録</x-button> </div> </div> </x-form> </div> </div> </div> </div> </div> </x-layout>
前回と違って、name="emails[1]"
のように配列の文字列となっていることに注意を。
なにかがおかしい!
上の画面で以下のようにEメールでない値を入れて「登録」ボタンを押すと、
もちろん、画面ではエラーが表示されることを期待しますが、何もでてきません。しかも、入力した値は空になってしまいます。まさに、最初の空の入力画面と同じ状態です。
ちなみに、バリデーションのルールは以下です。
'emails' => ['required', 'array'], 'emails.*' => ['string', 'email', 'max:255'],
何がおかしいのでしょう?
ここで、前回のx-inputのコンポーネントをここで再度掲載します。
@props([ 'type' => 'text', 'name', 'value' => null, ]) <input type="{{ $type }}" name="{{ $name }}" value="{{ old($name, $value) }}" @error($name) {{ $attributes->class('form-control is-invalid') }} @else {{ $attributes->class('form-control') }} @enderror /> @error($name) <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror
調査すると、問題はコンポーネントにおける、old($name, $value)
と@error($name)
に渡している$nameの値です。
配列なので、この$nameには、emails[1]、emails[2]、emails[3]の文字列が入ってきます。
しかし、old()はこれらの文字列を理解しません。@errorに関しては、debugbarでセッションを見ると、以下のように、emails[1]ではなく、emails.1という文字列になっています。
対応
ということは、old()や@error()に渡す指標が配列の文字列なら、ドットの文字列に変換すればよいですね。
以下は、改良したコンポーネントです。
@props([ 'type' => 'text', 'name', 'value' => null, ]) @php $index = str_replace(['.', '[]', '[', ']'], ['_', '', '.', ''], $name); // 'emails[1]'が'emails.1'となる @endphp <input type="{{ $type }}" name="{{ $name }}" value="{{ old($index, $value) }}" @error($index) {{ $attributes->class('form-control is-invalid') }} @else {{ $attributes->class('form-control') }} @enderror /> @error($index) <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror
これで再度「登録」ボタンを押すと、期待通りにエラーが表示されます。
メルマガ購読の申し込みはこちらから。