😽
LaravelのFormRequestでJsonStringをValidateする
前提
Form の submit で POST を投げるのと同時に付加情報として Form データ以外の情報を JsonString の形でを追加して送る必要があったので、調べました。
PostするときのContent-type
がapplication/x-www-form-urlencoded
でそこにJsonStringを付加する場合なので、最初からContent-type
がapplication/json
で送信する場合は、この対応は不要でふつうにドット記法でバリデーションできると思います。
実装
Blade側
Javascriptで送信前にObjというデータをJSON化して、hiddenパラメータのjsonとして付加してSubmitします。
<form action="{{ route('hoge.store') }}" method="post" id="form-hoge">
{{ Form::hidden('json', null) }} // 追加
...
{{ Form::text('id', null, ['class' => 'form-control']) }}
...
</form>
@section('script')
<script type="module">
...
// submit 前に json にデータを突っ込んで送信する
$('#form-hoge').submit(function() {
// 送りたいデータ
const obj = {
'hoge1': [
{ 'key': 'hoge1-1', 'value': 'hoge1-1-1' },
{ 'key': 'hoge1-2', 'value': 'hoge1-2-1' },
],
'hoge2': 'hoge2-2',
...
};
$('input[name=json]').val(JSON.stringify(obj));
return true;
})
...
</script>
@endsection
FormRequest側
キモはgetValidatorInstance
で、ここで JsonString を配列化し、data_array
という名前で FormRequest にセットします。rules
での判定実装はセットしたdata_array
に対しておこないます。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\Rule;
class HogePost extends FormRequest
{
...
// この getValidatorInstance を override する
protected function getValidatorInstance(): Validator
{
$json = $this->request->get('json');
$this->merge(['data_array' => $json_decode($json, true)]);
return parent::getValidatorInstance();
}
...
public function rules()
{
return [
'id' => ['required', 'integer'],
// json に Json が入ってくるかの Validation も必要
'json' => ['required', 'json' ],
// こういう感じで Jsonの 中身も Validate が簡単にかける
'data_array.hoge1.*.key' => ['required', 'string', 'max:50'],
'data_array.hoge1.*.value' => ['required', 'string', 'max:256'],
'data_array.hoge2' => ['required', 'string', 'max:10'],
...
];
}
...
Controller側
最後に引数にFormRequestを渡し、バリデーションの実行を行います。
public function store(HogePost $request)
{
// バリデーションの実行
$validated = $request->validated();
return ...
}
参考
Discussion