【Laravel5】FormRequest의 밸리데이션 결과를 JSON API로 돌려준다

기사가 개인 사이트로 이동했습니다.



개인 사이트/Qiita 모두 동일한 내용을 기재하고 있습니다 (2020/2/24 현재).

개요



예를 들어, 회원을 새로 추가하는 API의 엔드포인트가 있다고 가정합니다.
[POST] https://example.com/api/users

routes/api.php
Route::resource( 'users', 'Api\UsersController' )->only( ['store'] );

컨트롤러는 다음 상태입니다.

app/Http/Controllers/Api/UsersController.php
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Requests\StoreUserRequest;
use App\Http\Resources\UserResource;
use App\User;

class UsersController extends Controller
{
    /**
     * 会員追加
     *
     * @param StoreUserRequest $request
     * @return User
     */
    public function store( StoreUserRequest $request )
    {
        return User::create( $request->only( ['name'] ) ); 
    }
}


FormRequest 클래스는 다음 상태입니다.

artisan
$ php artisan make:request StoreUserRequest

app/Http/Requests/StoreUserRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required',
        ];
    }

    public function messages()
    {
        return [
            'name.required' => 'お名前を入力してください。',
        ];
    }
}

위의 API를 두드릴 때 "이름을 입력하십시오."
JSON 형식으로 오류 메시지를 반환하려는 경우를 생각해보십시오.

이 상태로 API를 두드려도 솔직하게 에러 응답이 반환되지 않습니다.
(welcome 페이지의 HTML이 반환됩니다)

원인과 대응



유효성 검사 실패 시 FormRequest 클래스 내에서 리디렉션이 발생하기 때문입니다.
참고 : Laravel5.1.x에서 API를 만들 때 신경 쓰이는 것을 조사했습니다. - Qiita

검증 실패시에도 JSON 형식으로 결과를 반환하도록 대응합니다.

Laravel5.4 이전


FormRequest::response() 를 오버라이드(override) 하는 것으로 대응 가능한 것 같습니다.

StoreUserRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\JsonResponse;  // 追加

class StoreUserRequest extends FormRequest
{
    /**
     * [override] バリデーション失敗時ハンドリング
     *
     * @param array $errors
     * @return JsonResponse
     */
    public function response( array $errors )
    {
        $response = [
            'data'    => [],
            'status'  => 'NG',
            'summary' => 'Failed validation.',
            'errors'  => $errors,
        ];
        return new JsonResponse( $response, 422 );
    }
}

Laravel 5.5 이상


FormRequest::response()는 폐지되었기 때문에 대신FormRequest::failedValidation() 를 오버라이드(override) 하는 것으로 대응합니다.

StoreUserRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;  // 追加
use Illuminate\Http\Exceptions\HttpResponseException;  // 追加

class StoreUserRequest extends FormRequest
{
    /**
     * [override] バリデーション失敗時ハンドリング
     *
     * @param Validator $validator
     * @throw HttpResponseException
     * @see FormRequest::failedValidation()
     */
    protected function failedValidation( Validator $validator )
    {
        $response['data']    = [];
        $response['status']  = 'NG';
        $response['summary'] = 'Failed validation.';
        $response['errors']  = $validator->errors()->toArray();

        throw new HttpResponseException(
            response()->json( $response, 422 )
        );
    }
}

실행 결과



이미지는 POSTMAN 캡처입니다.
엔드포인트를 두드려 JSON 응답이 반환되면 OK입니다.



API용 요청 클래스 만들기



API를 작성하는 경우는 응답 형식을 통일하게 된다고 생각하므로,
아래와 같은 추상 클래스를 작성하는 것이 좋을 것입니다.
Laravel5.8 FormRequest에서 검증 실패시 JsonResponse 반환 - Qiita

참고 기사


  • How to make a custom FormRequest error response in Laravel 5.5
  • Laravel5.1.x에서 API를 만들 때 신경 쓰이는 것을 조사했습니다. - Qiita
  • 좋은 웹페이지 즐겨찾기