Laravel 验证错误 自定义响应格式

9

我正在使用L5表单请求,我非常喜欢Taylor!现在,我正在进行一些AJAX请求,但仍然希望保留我的表单请求。问题是,在验证错误的情况下,验证器只返回422错误响应并闪烁错误,但我的AJAX前端期望从服务器接收一个非常特定的响应格式,无论验证是否成功。

我希望将验证错误的响应格式化为以下内容:

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个回答

22

目前被接受的回答已经不再适用,因此我提供了一个更新的答案。

在相关的FormRequest中,使用failedValidation函数抛出自定义的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);
}

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

这是我找到的唯一方法。如果有更好的方法,请留言评论。

这在laravel5.5中有效,我不确定在laravel5.4中是否有效。


我一直在L5.4中使用已接受的答案(由我自己提供 :)),并且尚未在5.4+中进行测试,因此如果您提供的答案有效,那就没问题了。 - gthuo

6

如果您在使用laravel 5+,您可以通过重写App/Exceptions/Handler.php文件中的invalid()invalidJson()方法来轻松实现此操作。

在我的情况下,我正在开发一个API,并且api响应应该采用特定格式,因此我在Handler.php文件中添加了以下内容。

/**
     * 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;
    }

1
有趣。想要尝试一下并看看它的工作原理。 - gthuo
很棒的想法。运行良好! - JCarlosR

2
\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);

}

1

在这里找到答案:Laravel 5自定义验证重定向
你需要做的就是在表单请求中添加一个response()方法,它将覆盖默认响应。在你的response()中,你可以以任何方式重定向。

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
}

L5.5+ 更新
这个错误和被接受的解决方案是针对L5.4的。对于L5.5,请使用上面Ragas的答案(failedValidation()方法)。


除了你概述的内容,你还需要做其他事情吗?我正在尝试你的解决方案,虽然我得到了一个响应,但JSON结构与我的格式化响应完全不同...请参见http://stackoverflow.com/questions/42100798/format-formrequest-validation-error-response - Kendall
1
我不需要再做什么,自那以后它一直很好地运作着。你的情况似乎已经得到处理,因为你已经接受了那个答案。 - gthuo
1
谁给这个点了踩,提出问题并建议更好的答案是公平的。 - gthuo
嗨。这似乎在Laravel 5.4中已经停止工作了。在5.5中,有一个名为failedValidation的方法,理想情况下应该可以做到同样的事情! - The Sammie

1
在 Laravel 8+ 中,您可以在 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);
        }
    });

如果你正在使用 Laravel 8+,这可能是最好的方法。 - Romek

1
这受到此帖和Shobi的回答的启发。为什么不保留Shobi答案中的transformErrors函数,然后简单修改Handler.php内部的render函数呢?一个例子可能是这样的:
/**
 * 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);
}

这使得invalidJson函数变得多余,并允许在每种异常类型上添加更细粒度的自定义JSON响应区分。已在Laravel 6.2上进行了测试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接