9

I am working with L5 Form Requests and don't I just love Taylor! Well, I am doing some AJAX requests and I still want to retain my form requests. The problem is that in the case of a validation error the Validator just returns a 422 error response and flashes the errors, but my AJAX frontend expects a very specific format of response from server whether validation is successful or not.

I want to format the response on Validation errors to something like this

return json_encode(['Result'=>'ERROR','Message'=>'//i get the errors..no problem//']);

My problem is how to format the response for the form requests, especially when this is not global but done on specific form requests.

I have googled and yet not seen very helpful info. Tried this method too after digging into the Validator class.

// added this function to my Form Request (after rules())
    public function failedValidation(Validator $validator)
{
    return ['Result'=>'Error'];
}

Still no success.

6 Answers 6

22

Currently accepted answer no longer works so i am giving an updated answer.

In the revelent FormRequest use failedValidation function to throw a custom exception

// add this at the top of your file
use Illuminate\Contracts\Validation\Validator; 
use App\Exceptions\MyValidationException;

protected function failedValidation(Validator $validator) {
    throw new MyValidationException($validator);
}

Create your custom exception in app/Exceptions

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Contracts\Validation\Validator;

class MyValidationException extends Exception {
    protected $validator;

    protected $code = 422;

    public function __construct(Validator $validator) {
        $this->validator = $validator;
    }

    public function render() {
        // return a json with desired format
        return response()->json([
            "error" => "form validation error",
            "message" => $this->validator->errors()->first()
        ], $this->code);
    }
}

This is the only way I found. If there is a better approach please leave a comment.

This works in laraval5.5, I don't think this will work in laravel5.4 but i am not sure.

Sign up to request clarification or add additional context in comments.

1 Comment

Have been using the accepted answer (by me :)) in L5.4 and have not tested it in 5.4+, so if the one you have given works, that's fine.
7

If you are in laravel 5+ you can easily achieve this, by overriding the invalid() or invalidJson() method in the App/Exceptions/Handler.php file

In my case, I was developing an API and the api responses should be in a specific format, so I have added the following in the Handler.php file.

/**
     * Convert a validation exception into a JSON response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Validation\ValidationException  $exception
     * @return \Illuminate\Http\JsonResponse
     */
    protected function invalidJson($request, ValidationException $exception)
    {
        return response()->json([
            'code'    => $exception->status,
            'message' => $exception->getMessage(),
            'errors'  => $this->transformErrors($exception),

        ], $exception->status);
    }

// transform the error messages,
    private function transformErrors(ValidationException $exception)
    {
        $errors = [];

        foreach ($exception->errors() as $field => $message) {
           $errors[] = [
               'field' => $field,
               'message' => $message[0],
           ];
        }

        return $errors;
    }

2 Comments

Interesting. Will want to try this one out and see how it works
Great idea. Works fine!
2

in \App\Exceptions\Handler

public function render($request, Throwable $e)
{

    if ($e instanceof ValidationException) {
        //custom response
        $response = [
            'success' => false,
            'message' => "validation error",
            'data' =>$e->errors()
        ];

        return response()->json($response, 422);
    }


    return parent::render($request, $e);

}

Comments

2

in laravel 8+ you can do this just in App/Exceptions/Handler.php

// Illuminate\Validation\ValidationException
    $this->renderable(function (ValidationException $e, $request) {
        if ($request->wantsJson()) {
            return response()->json([
                'status' => $e->getMessage(),
                'message' => $e->validator->errors(),
            ], 400);
        }
    });

1 Comment

This is probably the best approach if you're using Laravel 8+
1

Found the answer here: Laravel 5 custom validation redirection
All you need to do is to add a response() method in your form request and it will override the default response. In your response() you can redirect in whatever fashion you want.

public function response(array $errors)
{
    // Optionally, send a custom response on authorize failure 
    // (default is to just redirect to initial page with errors)
    // 
    // Can return a response, a view, a redirect, or whatever els
    return response()->json(['Result'=>'ERROR','Message'=>implode('<br/>',array_flatten($errors))]); // i wanted the Message to be a string
}

UPDATE on L5.5+
This error and the accepted solution was for L5.4. For L5.5, use Ragas' answer above (failedValidation() approach)

4 Comments

Did you have to do anything else other than what you outlined? I'm trying your solution and while I get a response the json structure is no where near my formatted response... see stackoverflow.com/questions/42100798/…
i did not have to do anything else, and it has worked well ever since. Your case seems to have already been handled since you have accepted the answer there.
whoever downvoted this, it would be fair enough to suggest what the issue is, and even suggest a better answer.
Hi. This seems to have stopped working with Laravel 5.4. In 5.5 there is a method called failedValidation that should Ideally do the same!
1

This is inspired by this post and the answer by Shobi. Why not keep the transformErrors function from the Shobi's answer and simply modify the render function inside Handler.php? An example would look like:

/**
 * Render an exception into an HTTP response.
 *
 * @param  Request  $request
 * @param Exception $exception
 * @return Response
 *
 * @throws Exception
 */
public function render($request, Exception $exception)
{
    if ($exception instanceof ValidationException) {
        return response()->json([
            'code' => $exception->status,
            'error' => $exception->getMessage(),
            'message' => $this->transformErrors($exception)
            ], $exception->status);
    }
    return parent::render($request, $exception);
}

This makes invalidJson function redundant and allows to add more fine-grained differentiation of custom json responses on each type of exception.

Tested on Laravel 6.2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.