Laravelでバリデーションのエラーレスポンスを変えてみる

プログラミング

Laravelでバリデーションを実装したい時に、FormRequestを使うことが多いと思います。

バリデーションに引っかかるとValidationExceptionエラーとして処理され、レスポンスステータスコードは422がデフォルトで返されます。

API実装でレスポンスをJSONで返したい場合やレスポンスステータスコードを422以外のものにしたいといった時に簡単に変える方法をまとめます。

Laravel側でどのように実装しているのか気になったため処理を追ってみました。

FormRequestクラスにバリデーションに引っかかった時にエラーが投げられる処理がありました。(128行目あたり)

    /**
     * Handle a failed validation attempt.
     *
     * @param  \Illuminate\Contracts\Validation\Validator  $validator
     * @return void
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function failedValidation(Validator $validator)
    {
        throw (new ValidationException($validator))
                    ->errorBag($this->errorBag)
                    ->redirectTo($this->getRedirectUrl());
    }

次に投げられているValidationExceptionクラスを見てみるとデフォルトで422をステータスコードとして指定しているのがわかります。(30行目あたり)

    /**
     * The status code to use for the response.
     *
     * @var int
     */
    public $status = 422;

通常、バリデーションに引っかかるとHTMLが返されてしまいます。

APIなどを実装しているときはJSONでエラーを返したいと思います。

そんな時にFormRequestクラスを継承したバリデーションを実装するクラスでfailedValidationメソッドを書き換えて上げれば実現できます。

/**
 * @param Validator $validator
 */
protected function failedValidation(Validator $validator)
{
    $response = response()->json([
        'status' => Response::HTTP_BAD_REQUEST,
        'errors' => $validator->errors(),
    ], Response::HTTP_BAD_REQUEST);
    throw new HttpResponseException($response);
}

jsonメソッドはデフォルトでステータスコード200を返すので、第2引数に返したいステータスコードを渡してあげることでそのステータスコードのエラーとして返されます。

実際はすべてのバリデーションクラスにこのメソッドを追加していくのはかなり手間がかかるので、Handler.phpでエラーのハンドリングをしてあげると無駄なコードが減ると思います。

コメント

タイトルとURLをコピーしました