Agustin
Agustin

Reputation: 255

laravel api not showing message from request validation

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.

Upvotes: 9

Views: 13068

Answers (9)

tomexsans
tomexsans

Reputation: 4527

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

Upvotes: 0

Riki krismawan
Riki krismawan

Reputation: 567

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',

                    ];
                }
        }
    }
}

Upvotes: 0

Syeikh Anugrah
Syeikh Anugrah

Reputation: 41

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));
}

Upvotes: 4

haris
haris

Reputation: 3875

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.

Upvotes: 2

Rinkal Jasani
Rinkal Jasani

Reputation: 598

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...

Upvotes: 19

Pietro La Grotta
Pietro La Grotta

Reputation: 327

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 );
    } );
}

Upvotes: 1

X-Adam
X-Adam

Reputation: 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);
}

Upvotes: -1

Binal Gajjar
Binal Gajjar

Reputation: 322

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));
}

Upvotes: 10

Agustin
Agustin

Reputation: 255

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));
}

Upvotes: 17

Related Questions