Laravelのバリデーションエラーで配列の位置を取り出す


申込みフォームなどで、ユーザー数が可変で、各ユーザーの名前と年齢を取得したい場合などに、下記のようなデータが送られてくるとします。

["users"] => [
    0 => [
        'name' => '太郎',
        'age' => 20,
    ],
    1 => [
        'name' => '次郎',
        'age' => 18,
    ],
]

このとき、n番目の配列内の特定の要素に対してバリデーションエラーのメッセージを表示したいときに、
n番目は、必ず指定してください。 のような形で、配列の位置を取り出す方法です。

対象バージョン

  • Laravel9.x

結論

attributeで :index あるいは :position を使う。
https://laravel.com/docs/9.x/validation#error-message-indexes-and-positions

実装

App/Http/Requests/UserRequest.php に対してrules及びattributesを設定する形での実装を行います。

ValidationRuleの作成

リクエストする際に、各ユーザーの nameage が必須であることのルールを設定します。
なお、下記のデータの前提として、日本語のLanguageFileを導入しているものとします。

Requests/UserRequest.php
public function rules()
{
    return [
        'users.*.name' => 'required',
        'users.*.age' => 'required',
    ];
}

このとき、エラーを取り出すと、下記のような出力となります。

users.1.nameは、必ず指定してください。
users.1.ageは、必ず指定してください。
users.2.nameは、必ず指定してください。
users.2.ageは、必ず指定してください。

適当にattributesを設定する

Requests/UserRequest.php
public function attributes()
{
    return [
        'users.*.name' => 'ユーザーの名前',
        'users.*.age' => 'ユーザーの年齢',
    ];
}

シンプルにこのように登録すると、出力は下記のような形となります。

ユーザーの名前は、必ず指定してください。
ユーザーの年齢は、必ず指定してください。
ユーザーの名前は、必ず指定してください。
ユーザーの年齢は、必ず指定してください。

このままでは、「どのデータに対してエラーとなっているのか」がわかりません。

配列の位置を取り出す

ここで本題となります。
公式ドキュメントののValidationの項目を参照すると、:index あるいは :position を利用することで、配列の位置(インデックス)を取得できるとの記載があります。

そのため、先程のattributesを下記のように書き換えると、

Requests/UserRequest.php
public function attributes()
{
    return [
        'users.*.name' => ':index番目のユーザーの名前',
        'users.*.age' => ':index番目のユーザーの年齢',
    ];
}

エラーの出力は、下記のようになります。

1番目のユーザーの名前は、必ず指定してください。
1番目のユーザーの年齢は、必ず指定してください。
2番目のユーザーの名前は、必ず指定してください。
2番目のユーザーの年齢は、必ず指定してください。

終わりに

この :index 及び :position については、Laravel9.xのリリースに際して実装されたようです。
従来は取り出すのが割と面倒だったようなので、嬉しいですね。