Laravel API データポスト時のバリデーションで弾かれた後、http://127.0.0.1:8000/にリダイレクトしてしまう

# 目的

- Laravel APIのバリデーションでpostデータが弾かれた時に初期画面にリダイレクトしてしまう問題を解決した話をまとめる

# 概要

- 最新のlaravelバージョンでの方法はこちら
    - [laravel API バリデーションエラー時にエラー内容をJSONで返す](https://qiita.com/miriwo/items/637961702389d6673489)

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いて導入 |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いて導入 |

# 前提情報

- LaravelをAPIサーバとして使用してる。
- `http://127.0.0.1:8000/api/infomation`にDBに格納して欲しいデータを持たせてpostした時にバリデーションチェックを行う実装をした。
- バリデーションにより弾かれた時はJSONで下記の様なレスポンスが欲しい。

    ```JSON
    {
        "summary": "バリデーションによりこのリクエストは拒否されました",
        "errors": {
            "infomation_title": [
                "infomation title は必須です"
            ]
        }
    }
    ```

# 問題

- バリデーションで弾かれた際に`http://127.0.0.1:8000/`のhtmlがレスポンスとして帰ってきてしまう。
    - 下記にレスポンスとして得られた`http://127.0.0.1:8000/`のコードの一部を記載する。

        <img width="694" alt="スクリーンショット 2020-05-26 12.47.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/8ab7cdbc-a513-8277-2de4-b39eef6f3beb.png">

# 原因

- バリデーションルールが記載されているファイルの継承元である`アプリ名ディレクトリ/vendor/laravel/framework/src/Illuminate/Validation/ValidatesWhenResolvedTrait.php `の`public function validateResolved()`らへんが悪さをしている様である。
- このためバリデーションルールが記載されているファイルは`FormRequest::failedValidation()`でバリデーションで弾かれた際にリダイレクトを行っているらしいのでこの部分の設定をバリデーションルールが記載されているファイルで上書き(オーバーライド)してあげる。

# 解決方法

1. 関数のオーバーライド
    1. 下記コマンドを実行してバリデーションルールが記載されたファイルを開く。

        ```terminal
        $ vi アプリ名ディレクトリ/app/Http/Requests/StoreContentPost.php
        ```
    1. 下記の内容を`class StoreContentPost extends FormRequest`内に記載する。

        ```アプリ名ディレクトリ/app/Http/Requests/StoreContentPost.php
        public function failedValidation(Validator $validator)
        {
            $response['summary'] = 'バリデーションによりこのリクエストは拒否されました';
            $response['errors']  = $validator->errors()->toArray();

            throw new HttpResponseException(
                response()->json($response)
            );
        }
        ```
1. 確認
    1.  あえてバリデーションで弾かれるデータを付与し、外部アプリから`http://127.0.0.1:8000/api/infomation`にpostする。
    1. 下記の様に期待値のレスポンスが帰ってくる事を確認する。

        <img width="549" alt="スクリーンショット 2020-05-26 13.34.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3617bbd2-cd26-514e-fd9b-68a95ec07817.png">
 


# 付録

1. バリデーションルールが記載されたファイルの全体を下記に記載する。

    ```アプリ名ディレクトリ/app/Http/Requests/StoreContentPost.php
    <?php
    
    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    
    //下記を追加する
    use Illuminate\Contracts\Validation\Validator;
    use Illuminate\Http\Exceptions\HttpResponseException;
    //上記までを追加する    

    j
    class StoreContentPost 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 [
                'infomation_title' => 'required',
                'infomation_content' => 'required',
                'infomation_period_start_date' => 'required|max:8',
                'infomation_period_end_date' => 'required|max:8',
            ];
        }
    
        public function failedValidation(Validator $validator)
        {
            $response['summary'] = 'バリデーションによりこのリクエストは拒否されました';
            $response['errors']  = $validator->errors()->toArray();
    
            throw new HttpResponseException(
                response()->json($response)
            );
        }
    }
    ```
     
# 参考文献

- [【Laravel5】FormRequestのバリデーション結果をJSON APIで返す](https://qiita.com/junsan50/items/ec7f810decd3b82d3d76#laravel55%E4%BB%A5%E9%99%8D)
- [Laravel5.1.xでAPIを作る際に気になっていたことを調べました](https://qiita.com/zaburo/items/f0db54bd3ebd81a8ce68)
- [【Laravel】フォームリクエストを使いつつ勝手にリダイレクトさせない](https://qiita.com/rana_kualu/items/77134af5477d27bf2cc2)
- [Laravel5.8 FormRequestでバリデーション失敗時にJsonResponseを返す](https://qiita.com/ucan-lab/items/bbf1da23198201ef130b#apirequest)