Laravel 配列のバリデーションで、ちょっと留意しておきたい点
Laravel 8.50で Validator::excludeUnvalidatedArrayKeys(); なる機能が追加されました。この機能を見がてら、Laravel で配列をバリデーションする際に、少し留意しておきたい点も確認してみます。
参考:GitHub [8.x] Add Validator::excludeArrays() to exclude .... #37943
参考:本家ドキュメント
現在、Laravel では、コントローラや FormRequest でバリデーションする際、
validate() 又は validated() メソッドを使って、バリデーションを通ったデータ(列挙した項目のみ)が返ってきますね。
まぁ、それは私でも知っている内容ですが、配列の場合は、そうではなかったんですね。
配列と言っても、幾つかタイプがあると思いますが、例えば次のような場合、
(コントローラを想定)
$input = [
'user' => [
'name' => 'taro',
'admin' => true,
],
];
$data = validator()->validate($input, [
'user' => ['required', 'array'],
'user.name' => ['required'],
]);
dd($data);
dd($data); の結果は、
array:1 [▼
"user" => array:2 [▼
"name" => "taro"
"admin" => true
]
]
'admin' の方は、バリデーションしてないのに、$data に含まれてしまっているんですね。これはちょっと嬉しくないです。
ではどういう対策があるかと言うと、'array'にオプションで項目を指定して、以下のようにしてやれば OK となります。(項目複数あったらカンマ区切り)
$data = validator()->validate($input, [
'user' => ['required', 'array:name'], // ここ
'user.name' => ['required'],
]);
こうすれば、'admin' などという項目が飛んできたら、バリデーションエラーになります。
一方、ワイルドカードを使うタイプの話で以下のような場合、
$input = [
'users' => [
1 => [
'name' => 'taro',
'admin' => true,
],
2 => [
'name' => 'jiro',
'admin' => true,
],
],
];
$data = validator()->validate($input, [
'users' => ['required', 'array'],
'users.*.name' => ['required'],
]);
dd($data);
dd($data); の結果は、
array:1 [▼
"users" => array:2 [▼
1 => array:2 [▼
"name" => "taro"
"admin" => true
]
2 => array:2 [▼
"name" => "jiro"
"admin" => true
]
]
]
'admin' が入ってしまっています。今回は、キーは添え字(数字)なので、先の方法そのままではうまく行きません。
こちらの場合は、Ver. 8.50 で追加された機能を利用すれば、
AppServiceProvider
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Validator::excludeUnvalidatedArrayKeys();
今度は下記のように含まれなくなります。
array:1 [▼
"users" => array:2 [▼
1 => array:1 [▼
"name" => "taro"
]
2 => array:1 [▼
"name" => "jiro"
]
]
]
この機能が有効なのは、こちらのワイルドカードを使ったバリデーションの時のみですね。 Ver.8.51 で修正され、ワイルドカードのタイプのみならず、最初に紹介したタイプでも有効です。
雑感
もしかしたら、リリースが来年2月に伸びた Ver.9 で、この機能の挙動がデフォルトになるかも知れません。まぁ、Ver.9 のリリースは伸びましたが、新機能は随時追加されていますね(breaking change でない限り)。
間違い等ありましたらコメントお願いします。
Discussion