Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cizario's avatar

how to catch 422 (Unprocessable Entity) error in the proper way ?

hi, i'm trying to build a very simple Laravel app with 2 controllers (FrontController and SubmissionsController) using jquery and ajax to submit and validate the submission form.

when the validation passes, every thing seems working as expected but when it fails i keep getting in the console 422 (Unprocessable Entity) and this the normal and the default behavior of Laravel. So my concern is how to handle this error or precisely how to override the default behavior of laravel in the proper way ?

i'm using laravel 5.4

Route::group(['middleware' => ['web']], function () {

# Front Page
Route::get('/{locale}', ['as' => 'index', 'uses' => '\App\Http\Controllers\Front\FrontController@index']);

# Ajax
Route::post('/{locale}/submission/ajax', ['as' => 'submission.store',  'uses' => '\App\Http\Controllers\Front\SubmissionsController@ajax']);

});

class FrontController extends Controller 
{
    public function index($locale)
    {
        app()->setLocale($locale);
        return view('front.pages.index');
    }
}
class SubmissionsController extends Controller 
{
    /**
     * Store a newly created resource in storage.
     *
     * @param  SubmissionFormRequest $request
     * @return Response
     */
    public function ajax(SubmissionFormRequest $request, $locale)
    {
        app()->setLocale($locale);
        // if ($request->ajax()) {
        $validator = \Validator::make($request->all(), $request->rules());
        
        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()->all()]);
        }
        
        $submission = new Submission;
        $submission->first_name = $request->get('first-name');
        $submission->last_name  = $request->get('last-name');
        $submission->email      = $request->get('email');
        $submission->notify_me  = $request->has('notify-me');
        $submission->save();
    
        return response()->json(['message' => 'ok']);
        // }
    }
}

class SubmissionFormRequest 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 [
            'first-name' => 'required',
            'last-name'  => 'required',
            'email'      => 'required|email|unique:submissions'
        ];
    }

}
<form id="form-submission" novalidate role="form">
     {!! csrf_field() !!}
         <div class="form-group form-row">
            <div class="col">
                    <input type="text" class="form-control rounded-0" name="first-name" value="" placeholder="{{ __('Votre nom *') }}" required>
                        <div class="invalid-feedback"></div>
                </div>
                <div class="col">
                    <input type="text" class="form-control rounded-0" name="last-name" value="" placeholder="{{ __('Votre prénom *') }}" required>
                        <div class="invalid-feedback"></div>
                </div>
        </div>
                
        <div class="form-group">
            <input type="email" class="form-control rounded-0" name="email" value="" placeholder="{{ __('Votre e-mail *') }}" required>
                <div class="invalid-feedback"></div>
        </div>

        <div class="form-group">
        <div class="form-check">
                    <input type="checkbox" class="form-check-input" name="notify-me" id="notify-me">
                        <label class="form-check-label" for="notify-me">{{ __('Notifiez-moi de nouvelles publications.') }}</label>
               </div>
        </div>

        <div class="form-group">
            <button type="submit" class="btn btn-default rounded-0">{{ __('Télécharger le livre blanc') }}</button>
        </div>
                    
    <small class="form-text text-muted">{{ __('Les champs marqués avec (*) sont obligatoires.') }}</small>

</form>
  var $form = $('#form-submission');
  $form.submit(function(e) {

    // console.log($form.serialize());
    e.preventDefault();

    // var _token = $('input[name=_token]').val();  
    // var first_name = $('input[name=first-name]').val();
    // var last_name = $('input[name=last-name]').val();
    // var email = $('input[name=email]').val();
    // var notify_me = $('input[name=notify-me]').val();

    $.ajax({
      url: "/fr/submission/ajax",
      type: "POST",
      // headers: { "X-XSRF-TOKEN" : $('input[name=_token]').val() },
      dataType: "application/json",
      data: $form.serialize(),
      
      success: function(json) {
        console.log(json);
      },
      
      error: function(json) {
        console.log(json);
      }
      
    }); 
  }); 
0 likes
6 replies
tykus's avatar

This is unnecessary if you also are using FormRequest:

$validator = \Validator::make($request->all(), $request->rules());
        
if ($validator->fails()) {
    return response()->json(['errors' => $validator->errors()->all()]);
}

The request has been authorised and validated simply by typehinting the SubmissionFormRequest.

What do you mean:

... how to handle this error or precisely how to override the default behavior of laravel in the proper way?

2 likes
cizario's avatar

@tykus , yes i confirm your point.

so since i'm using "my custom" form request to validate the form, how can i do to return "my custom" json object with status 200 not 422 by default when the validation fails ?

rawilk's avatar

In your response, you can pass the code in as a second parameter, like this: return response()->json($data, 422);, although the request class should do that for you when validation fails.

2 likes
tykus's avatar

Get rid of the SubmissionFormRequest altogether and manually validate inside the controller (as you had earlier):

    public function ajax(Request $request, $locale)
    {
        app()->setLocale($locale);

        $validator = \Validator::make($request->all(), $request->rules());
        
        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()->all()]);
        }
        
        $submission = new Submission;
        $submission->first_name = $request->get('first-name');
        $submission->last_name  = $request->get('last-name');
        $submission->email      = $request->get('email');
        $submission->notify_me  = $request->has('notify-me');
        $submission->save();
    
        return response()->json(['message' => 'ok']);
        // }
    }
}

Or, if you always want this custom behaviour, you could keep the SubmissionFormRequest and catch a thrown ValidationException inside the App\Exceptions\Handler class and define the response you prefer:

public function render($request, Exception $exception)
{
        if ($exception instanceof ValidationException) {
                return response()->json([], 200);
        }

        return parent::render($request, $exception);
}
1 like
cizario's avatar
cizario
OP
Best Answer
Level 1

@tykus, @wilk_randall thank you all guys

the solution was simple and clean and proper as per this tutorial of Matt Stauffer https://mattstauffer.com/blog/laravel-5.0-form-requests/ section 4.Create your FormRequest

i just overrided the response function in my SubmissionFormRequest

in Illuminate\Foundation\Http\FormRequest

class FormRequest extends Request implements ValidatesWhenResolved
{
// ...

    /**
     * Get the proper failed validation response for the request.
     *
     * @param  array  $errors
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function response(array $errors)
    {
        if ($this->expectsJson()) {
            return new JsonResponse($errors, 422);
        }

        return $this->redirector->to($this->getRedirectUrl())
                                        ->withInput($this->except($this->dontFlash))
                                        ->withErrors($errors, $this->errorBag);
    }

// ...
}

in my SubmissionFormRequest

namespace App\Http\Requests;

use Illuminate\Http\JsonResponse;
use Illuminate\Foundation\Http\FormRequest;

class SubmissionFormRequest 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 [
            'first-name' => 'required',
            'last-name'  => 'required',
            'email'          => 'required|email|unique:submissions'
        ];
    }

    /**
     * Get the proper failed validation response for the request.
     *
     * @param  array  $errors
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function response(array $errors)
    {
        if ($this->expectsJson()) {
            return new JsonResponse($errors, 200);
        }
    }

}

hope this help someone else.

1 like

Please or to participate in this conversation.