laravel api not showing message from request validation
Asked Answered
M

9

8

im having problems with error handler in my backend laravel api, don't show error message from validation.

routes/api

<?php
Route::group([

    'middleware' => 'api',

], function ($router) {
    Route::post('access/sign-up', 'AuthenticationController@signUp');
});

AuthenticationController

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\SignUpRequest;
use Illuminate\Http\Request;
use App\User;


    class AuthenticationController extends Controller
    {
        /**
         * Create a new AuthenticationController instance.
         *
         * @return void
         */
        public function __construct()
        {
            $this->middleware('auth:api', ['except' => ['signUp']]);
        }


        /**
         * 
         *
         * @return \Illuminate\Http\JsonResponse
         */
        public function signUp(SignUpRequest $request)
        {
            //User::create($request->all());
            return response()->json([
                'data' => 'Usuario creado correctamente.'
            ]);
        }
    }

SignUpRequest

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SignUpRequest 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 [
            'email' => 'required|email|unique:users',
            'firstName' => 'required',
            'password' => 'required',
        ];
    }


}

The thing is that when by postman i send password in blank or not send mail for example it send me to main page insted of sending me a json with all the errors like before. I don't know what to do. I tryed with custom message in SignUpRequest, but that's not the problem, think some kind of redirect in error handler.

Maim answered 3/2, 2019 at 16:9 Comment(4)
While You are using the form requests it won't return json use the validator facade inside the controller and send the response if the validator failsUnderbelly
Could be that in previos version (5.6) I can use that way and work sending me the json with the different errors? How can I use the validation facade instead?Maim
Thanks for guide me. I resolve adding protected function failedValidation(Validator $validator) { throw new HttpResponseException(response()->json($validator->errors(), 422)); }Maim
I think the right approach is to add an exception handler: laravel.com/docs/8.x/errorsLegation
M
17

Just add that code to SignUpRequest

 use Illuminate\Contracts\Validation\Validator;
 use Illuminate\Http\Exceptions\HttpResponseException;



protected function failedValidation(Validator $validator)
{
    throw new HttpResponseException(response()->json($validator->errors(), 422));
}
Maim answered 3/2, 2019 at 17:17 Comment(1)
it's works for me. I'm using laravel 10 with vue 3. ThanksHegemony
D
18

You need to check just one setting must add Accept Type in header data in Postman

Accept : application/json

that is work in my case...

Danby answered 23/3, 2021 at 6:41 Comment(0)
M
17

Just add that code to SignUpRequest

 use Illuminate\Contracts\Validation\Validator;
 use Illuminate\Http\Exceptions\HttpResponseException;



protected function failedValidation(Validator $validator)
{
    throw new HttpResponseException(response()->json($validator->errors(), 422));
}
Maim answered 3/2, 2019 at 17:17 Comment(1)
it's works for me. I'm using laravel 10 with vue 3. ThanksHegemony
M
10

Using the Form request; If validation fails, a redirect response will be generated to send the user back to their previous location. That's why you are redirecting back to the page instead of the response JSON.

Laravel have one protected method "failedValidation" method. Overwrite this method in your form request class.

  protected function failedValidation(\Illuminate\Contracts\Validation\Validator $validator)
{

    throw new \Illuminate\Validation\ValidationException(response()->json($validator->errors(), 422));
}
Manifestation answered 4/2, 2019 at 11:8 Comment(1)
I didn't find this even in Laravel's official document, you saved my day, thanks!Misunderstood
V
4

Update for laravel 8, the first parameter in ValidationException is the Validator class:

protected function failedValidation(Validator $validator)
{
    throw new ValidationException($validator, response()->json($validator->errors(), 422));
}
Vedette answered 2/7, 2021 at 2:40 Comment(0)
D
2

TL;DR Add the following header: Accept: application/json

As mentioned by a few users over here, by default, when a Form Request fails, the application will attempt to redirect the user back to their previous location. That's why you're receiving a webpage instead of a JSON response.

We can also override the "failedValidation" method. But I would recommend setting the following header on the request Accept: application/json.

Laravel will return the appropriate response based on Accept header. For application/json Laravel will return a JSON response with form errors.

Drews answered 8/3, 2021 at 10:23 Comment(0)
P
1

Simply, in your App\Exceptions\Handler, you have to register your custom exception handling in register() method:

public function register() {
    
    $this->renderable( function ( ValidationException $ex, $request ) {
        
        $response = [
            'ErrorCode' => 'my_error_code',
            'ErrorMessage' => $ex->validator->errors()
        ];
        
        return response()->json( $response );
    } );
}
Printable answered 1/10, 2020 at 11:48 Comment(0)
C
0

add this method to your formRequest class. It works in laravel 9

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

class PostRequest extends FormRequest
{
    protected function failedValidation(Validator $validator)
    {
        throw new HttpResponseException(response()->json([
            'success' => false,
            'message' => 'Validation errors',
            'data'    => $validator->errors(),
        ]));
    }
    /**
     * 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()
    {
        switch ($this->method()) {
            case 'GET':
            case 'DELETE':{
                    return [];
                }
            case 'POST':{
                    return [
                        'title' => 'string|unique:posts|required',
                        'body'  => 'required',
                        'image' => 'string|nullable',

                    ];
                }
            case 'PUT':{
                    return [
                        'title' => 'string|unique:posts|required',
                        'body'  => 'required',
                        'image' => 'string|nullable',

                    ];
                }
        }
    }
}
Calorific answered 11/5, 2022 at 9:2 Comment(0)
E
0

In laravel 9/10

In my case i have a small POST API controller that handles a short logic.

I would like to contain it into the class only and not use any FormRequest rules as it has only 1 method to create a resource and only 1 parameter

this is what i did:

    // use Illuminate\Support\Facades\Validator;
    // use Illuminate\Http\Exceptions\HttpResponseException;
    $validator = Validator::make($request->all(), [
        'mac_address' => ['required',new MacArrayCheck]
    ]);

    if ($validator->fails()) {
        throw new HttpResponseException(response()->json($validator->errors(), 422));
    }
 
    // ... logic here when all validations passes

Read more here Laravel 10 Doc Manual Validation

Eldrid answered 29/6, 2023 at 5:43 Comment(0)
I
-1

Just add that code to App\Exceptions\Handler:

public function render($request, Exception $exception)
{
    if ($exception instanceof ValidationException) {
    return response()->json([
            'status' => false,
            'error' => [
                'type' => 'form',
                'code' => 400,
                'description' => 'Bad request.',
                'detail' => $exception->validator->errors()
            ]
        ], 422);
    }

    return parent::render($request, $exception);
}
Igloo answered 22/6, 2020 at 16:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.