結論
LaravelでPOSTデータ(JSON)とGETデータを同時にFormRequestでバリデーションする方法は、validationDataをオーバーライドして受け取ったデータを再生成することで解決できます。
実際のデータ
http://example.com/api/v1/chairs?t=2022-12&w=1
[
{
"day": "2022-12-19",
"hoge": 5,
"fuga": 1,
"hogehoge": [
1,
2
]
},
{
"day": "2022-12-05",
"hoge": 2,
"fuga": 1,
"hogehoge": [
1,
2
]
}
]
コード
public function rules()
{
$rules = [
'query.t' => 'required|date_format:Y-m',
'query.w' => 'required|integer|between:0,6',
];
// メソッドがPOSTの場合のルール
if ($this->method() == 'POST') {
$rules = [
'json.*' => 'required|array',
'json.*.day' => 'required|date',
'json.*.hoge' => 'required|integer',
'json.*.fuga' => 'required|integer',
'json.*.hogehoge' => 'required|array',
'json.*.hogehoge.*' => 'required|int',
'query.t' => 'required|date_format:Y-m',
'query.w' => 'required|integer|between:0,6',
];
}
return $rules;
}
public function validationData()
{
return [
'json' => $this->except('t', 'w'),
'query' => $this->only('t', 'w')
];
}
解説
データの再形成
以下のコードがポイントで、バリデーション対象のデータを受け取り、jsonに対してGETパラメーターのtとwを除いたものを収納しています。
queryに対してGETパラメーターのtとwのデータを収納しています。
public function validationData()
{
return [
'json' => $this->except('t', 'w'),
'query' => $this->only('t', 'w')
];
}
バリデーション部分
今回の場合、少し特殊で、GETとPOSTでのルールを分けています。
jsonの配列は繰り返すので"*"で処理
再形成せず直接t,wだけ入れるとt.*.dayなどと無いはずのものも検証対象とされてしまう…
public function rules()
{
// 基本は、このルールで。(GET)
$rules = [
'query.t' => 'required|date_format:Y-m',
'query.w' => 'required|integer|between:0,6',
];
// メソッドがPOSTの場合のルール上書き
if ($this->method() == 'POST') {
$rules = [
'json.*' => 'required|array',
'json.*.day' => 'required|date',
'json.*.hoge' => 'required|integer',
'json.*.fuga' => 'required|integer',
'json.*.hogehoge' => 'required|array',
'json.*.hogehoge.*' => 'required|int',
'query.t' => 'required|date_format:Y-m',
'query.w' => 'required|integer|between:0,6',
];
}
return $rules;
}
更新系(PUT, PATCH)時にのみバリデーション制御するということも可能です。
// メソッドがPUT, PATCHの場合のルール
if (in_array($this->method(), ['PUT', 'PATCH'])) {
$rules = [
'hoge' => ['required', 'string', 'max:255', Rule::unique('hoges')->ignore($this->hoge)],
];
}