😽

LaravelのFormRequestでJsonStringをValidateする

2021/02/01に公開

前提

Form の submit で POST を投げるのと同時に付加情報として Form データ以外の情報を JsonString の形でを追加して送る必要があったので、調べました。

PostするときのContent-typeapplication/x-www-form-urlencodedでそこにJsonStringを付加する場合なので、最初からContent-typeapplication/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 ...
    }

参考

https://laracasts.com/discuss/channels/laravel/form-request-validation-for-json-parameter

Discussion