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でエラーのハンドリングをしてあげると無駄なコードが減ると思います。
コメント