先に結論
Laravelのパラメータ付きのバリデーションルールを使う時には空白を含まないように注意する。
事象
Laravelで構築されたバックエンドシステムに実装されているAPIへのリクエストをバリデーションするために下記のルールを設定していた。
'item_id' => 'int',
'name' => 'required_without:item_id | string'
「IDが指定されていない場合、nameは必須で文字列である」という意味のルールになっている。
これに対して下記のリクエストを投げた。
{
"item_id" => 100
}
idが指定され、nameが任意項目になったはずなので、これは通るはずなのだがなぜかrequired_withoutエラーになってしまう。
推測と調査
required_withoutのパラメータで指定されている「item_id」が正しく認識されておらず、存在しないと勘違いしているのでは?と考えた。
そこで、required_withoutの本体であるIlluminate\Validation\Concerns\ValidatesAttributesのvalidateRequiredWithoutメソッドで$parametersを出力してみることにした。
public function validateRequiredWithout($attribute, $value, $parameters)
{
var_dump( $parameters);
if ($this->anyFailingRequired($parameters)) {
return $this->validateRequired($attribute, $value);
}
return true;
}
すると、下記の結果になった。
array(1) {
[0]=>
string(9) "item_id "
}
"item_id "と最後に空白文字が一文字入っていることがわかった。
どうやらこのせいで項目が認識できていないようだ。
そこで、下記のようにルールを書き換えた。
'item_id' => 'int',
'name' => 'required_without:item_id|string'
パイプの前後の空白文字を消してみた。
これで同じリクエストをしたところ、正常にリクエストが通った。
結論
パラメータは空白を含んで認識されるので、空白を入れないようにすること。
念の為、required_without以外にも下記のようにlteやrequired_withでも試したが同様だった。
'item_id' => 'int',
'name' => ['lte:item_id','string']
この事から、全てのパラメータ付きルールで同じ事象になると思われるので、全体的に注意が必要になる。
また、下記のように配列形式での指摘も試してみたが、同様の事象が起きていたので指定方法に限らず空白を入れないようにしておきたい。
'item_id' => 'int',
'name' => ['required_without:item_id','string']