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


目的

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

実施環境

  • ハードウェア環境
項目 情報
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で下記の様なレスポンスが欲しい。

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

問題

  • バリデーションで弾かれた際にhttp://127.0.0.1:8000/のhtmlがレスポンスとして帰ってきてしまう。

    • 下記にレスポンスとして得られたhttp://127.0.0.1:8000/のコードの一部を記載する。

原因

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

解決方法

  1. 関数のオーバーライド

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

      $ vi アプリ名ディレクトリ/app/Http/Requests/StoreContentPost.php
      
    2. 下記の内容を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)
          );
      }
      
  2. 確認

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

付録

  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)
            );
        }
    }
    

参考文献