LaravelでFormRequest使ってJSONをValidateする　って、どんな呪文だ？

Laravelって、気が付くとcontrollerがひどいことになるよね。MVCの宿命かもしれないけど。
今回はAPIの処理で受け取ったJSONのvalidationをFormRequestを使ってやってみるよ。
下記サイトをバリ参考にしました。ありがとうございます。
[Laravelを使ったAPI開発でController内のバリデーションをFormRequestに抽出して幸せになろう](https://nakka-k.hatenablog.com/entry/2019/06/04/191906)

ちなみに環境は下記の通り
Laravel 7.13.0
OS　Windows10
開発環境　homestead
DB　mysql

#１．チェックしたいJSON
こんな感じのデータをチェックするよ。

```json
{		
    "company_id" : "12345"	,
    "company_name" : "corp XXX",
    "branches" : [	
        {"no" : "1", 
         "branch_code" : "0123",
         "branch_name" : "ABC"
        }
        {"no" : "2", 
         "branch_code" : "9876",
         "branch_name" : "XYZ"
        }
    ]	
}
```
配列の中に更に配列があるパターンだね。
APIでこれをもらってきて、必須チェックとか数字チェックとかするよ。

#２．考え方
イメージとして、controllerでJSONを受け取るとき、まさに受け取るところでValidationをかけます。
これは、受け取るときのパラメータの書き方を、通常の(Request \$request）から、(《FormRequestの名前》 \$request)にして、FormRequestを通ってきたものを使うようにすればよいのです。

```php:contollerの例
public function store (JsonRequest $request)
{
    //普通に処理を書いていく
    //$reqesutはvalidation実行後のものになる

}
```

では、FormRequestを書いていこう。

#３．FormRequestの中身
まずは例によってartisanでrequestを作成するよ。
今回は「JsonRequest」という名前のrequestを作成します。

```cmd
php artisan make:request JsonRequest
```

そうすると、/app/Httpの下に「Requests」というフォルダーが作成され、その中に「JsonRequest.php」が作成される。

```php:JsonRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;

class JsonRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
            ];
    }
}
```

こんな感じ。

public function authorize()は認証関係のチェックを行う用のfunctionです。
認証なんて何もしないよ！という人はreturnをtrueに変更してください。でないと常にfalseが返ってしまい、いつまでも認証エラーです。

piblic function rules()の中に、validationのルールを書いていきます。
書き方は普通のlaravelのvalidationの書き方と同じです。
[公式マニュアルはこちら](https://readouble.com/laravel/7.x/ja/validation.html)
今回はこんな風に書いてみました。
companyテーブルは、そういうものがあるつもりで考えてね。

```php:JsonRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;

class JsonRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
            'company_id' => 'exists:company,id',  //comapnyテーブルの存在チェック
            'company_code' => 'numeric',    //数字であること
            'branches.*.no' => ['numeric', 'distinct'],   //数字、かつ重複チェック
            'branches.*.branch_code' => 'numeric',    //数字であること
            ];
    }
}
```

普通はこれでいいんだけど、FormRequestは基本画面から呼ばれた前提で処理が作られており、エラーが発生したとき画面にエラーメッセージを返そうとします。
今回はAPIで受け取っているので、エラー情報の返却もJSONで返したい。
なので、レスポンスをJSONで返す処理を追加します。

```php:JsonRequest.php

    //public function rulesの後とか、適当なところに追加

    protected function failedValidation(Validator $validator)
    {
        $res = response()->json([
            'status' => 400,
            'errors' => $validator->errors(),
        ],400);
        throw new HttpResponseException($res);
    }
```
もし独自のチェックをしたいとか、validationでない処理もしたいとか考えているなら、public function withValidatorに$varidator->afterとか追加すれば実現できます。ここでは書かないけど。

ここまで出来たら、最初に書いたようにcontrollerにJsonRequestを追加してください。

```php:JsonController.php
// 必要なところだけ抜粋
//最初にJsonRequestを取り込んでね
use App\Http\Requests\JsonRequest;

//途中省略

    public function store(JsonRequest $request)
    {
     //普通に処理を書く
     //validateはもう実行済み

    }
```
こうすると、あら不思議。勝手にvalidateされちゃいます。
メッセージの変更の仕方とかは、別の人の記事を探してね。

まずは、めでたしめでたし。