如何以 JSON 格式发送 Laravel 错误响应

Posted

技术标签:

【中文标题】如何以 JSON 格式发送 Laravel 错误响应【英文标题】:How to send Laravel error responses as JSON 【发布时间】:2015-04-11 05:54:03 【问题描述】:

我只是移动到 laravel 5 并且我在 html 页面中收到来自 laravel 的错误。像这样的:

Sorry, the page you are looking for could not be found.

1/1
NotFoundHttpException in Application.php line 756:
Persona no existe
in Application.php line 756
at Application->abort('404', 'Person doesnt exists', array()) in helpers.php line 

当我使用 laravel 4 时一切正常,错误是 json 格式,这样我就可以解析错误消息并向用户显示消息。 json错误示例:

"error":
"type":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
"message":"Person doesnt exist",
"file":"C:\\xampp\\htdocs\\backend1\\bootstrap\\compiled.php",
"line":768

我如何在 laravel 5 中实现这一点。

对不起,我的英语不好,非常感谢。

【问题讨论】:

【参考方案1】:

Laravel 5 在app/Exceptions/Handler.php 中提供了一个异常处理程序。 render 方法可用于以不同方式呈现特定异常,即

public function render($request, Exception $e)

    if ($e instanceof API\APIError)
        return \Response::json(['code' => '...', 'msg' => '...']);
    return parent::render($request, $e);

就我个人而言,当我想返回 API 错误时,我使用App\Exceptions\API\APIError 作为一般异常来抛出。相反,您可以只检查请求是否为 AJAX (if ($request->ajax())),但我认为显式设置 API 异常似乎更简洁,因为您可以扩展 APIError 类并添加您需要的任何功能。

【讨论】:

【参考方案2】:

我之前来这里是为了寻找如何在 Laravel 的任何地方抛出 json 异常,答案让我走上了正确的道路。对于发现此搜索类似解决方案的任何人,以下是我在应用程序范围内实施的方式:

将此代码添加到app/Exceptions/Handler.phprender方法中

if ($request->ajax() || $request->wantsJson()) 
    return new JsonResponse($e->getMessage(), 422);

将此添加到处理对象的方法中:

if ($request->ajax() || $request->wantsJson()) 

    $message = $e->getMessage();
    if (is_object($message))  $message = $message->toArray(); 

    return new JsonResponse($message, 422);

然后在任何你想要的地方使用这段通用代码:

throw new \Exception("Custom error message", 422);

它会将 ajax 请求后抛出的所有错误转换为 Json 异常,以便以任何你想要的方式使用:-)

【讨论】:

如果 Laravel 5.1,返回应该是“return response()->json($e->getMessage(), 422);” 这行得通。当处理代码不存在时,Laravel 会返回 HTTP 500 错误,而不管代码中抛出的具体错误是什么。例如。 abort(403) 会为 ajax 请求返回 500 错误。你有同样的经历吗?这一定是个bug? 这救了我的命。现在是 2017 年,我仍在使用 5.1,所以这对我来说真的很有用。在处理 FatalErrorException 时,我将 200 传递给第二个参数,因为我希望用户收到带有有用消息的警报,而不是像 Internal Server Error 这样的晦涩消息。这可以让页面正常呈现并为用户提供有用的反馈。【参考方案3】:

Laravel 5.1

将我的 HTTP 状态代码保留在意外异常上,例如 404、500 403...

这是我使用的(app/Exceptions/Handler.php):

 public function render($request, Exception $e)

    $error = $this->convertExceptionToResponse($e);
    $response = [];
    if($error->getStatusCode() == 500) 
        $response['error'] = $e->getMessage();
        if(Config::get('app.debug')) 
            $response['trace'] = $e->getTraceAsString();
            $response['code'] = $e->getCode();
        
    
    return response()->json($response, $error->getStatusCode());

【讨论】:

【参考方案4】:

编辑:Laravel 5.6 处理得非常好,无需任何更改,只需确保您将 Accept 标头发送为 application/json


如果你想保留状态码(这对前端理解错误类型很有用)我建议在你的 app/Exceptions/Handler.php 中使用它:

public function render($request, Exception $exception)

    if ($request->ajax() || $request->wantsJson()) 

        // this part is from render function in Illuminate\Foundation\Exceptions\Handler.php
        // works well for json
        $exception = $this->prepareException($exception);

        if ($exception instanceof \Illuminate\Http\Exception\HttpResponseException) 
            return $exception->getResponse();
         elseif ($exception instanceof \Illuminate\Auth\AuthenticationException) 
            return $this->unauthenticated($request, $exception);
         elseif ($exception instanceof \Illuminate\Validation\ValidationException) 
            return $this->convertValidationExceptionToResponse($exception, $request);
        

        // we prepare custom response for other situation such as modelnotfound
        $response = [];
        $response['error'] = $exception->getMessage();

        if(config('app.debug')) 
            $response['trace'] = $exception->getTrace();
            $response['code'] = $exception->getCode();
        

        // we look for assigned status code if there isn't we assign 500
        $statusCode = method_exists($exception, 'getStatusCode') 
                        ? $exception->getStatusCode()
                        : 500;

        return response()->json($response, $statusCode);
    

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

【讨论】:

这很好用,返回一个带有堆栈跟踪的巨大 json,但可以很容易地看到顶部的最后一个错误【参考方案5】:

代替

if ($request->ajax() || $request->wantsJson()) ...

使用

if ($request->expectsJson()) ...

供应商\laravel\framework\src\Illuminate\Http\Concerns\InteractsWithContentTypes.php:42

public function expectsJson()

    return ($this->ajax() && ! $this->pjax()) || $this->wantsJson();

【讨论】:

解释你的答案,以便 OP 和未来的读者更好地理解。【参考方案6】:

我更新了我的 app/Exceptions/Handler.php 以捕获不是验证错误的 HTTP 异常:

public function render($request, Exception $exception)

    // converts errors to JSON when required and when not a validation error
    if ($request->expectsJson() && method_exists($exception, 'getStatusCode')) 
        $message = $exception->getMessage();
        if (is_object($message)) 
            $message = $message->toArray();
        

        return response()->json([
            'errors' => array_wrap($message)
        ], $exception->getStatusCode());
    

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

通过检查getStatusCode()方法,可以判断异常是否可以成功强制转换为JSON。

【讨论】:

【参考方案7】:

在 Laravel 5.5 上,您可以在 app/Exceptions/Handler.php 中使用 prepareJsonResponse 方法,该方法将强制响应为 JSON。

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)

    return $this->prepareJsonResponse($request, $exception);

【讨论】:

又好又简单!但是,向客户端显示所有这些消息是否安全?【参考方案8】:

如果你想得到 json 格式的异常错误,那么 在 App\Exceptions\Handler 打开 Handler 类并自定义它。 这是未经授权请求和未找到响应

的示例
public function render($request, Exception $exception)

    if ($exception instanceof AuthorizationException) 
        return response()->json(['error' => $exception->getMessage()], 403);
    

    if ($exception instanceof ModelNotFoundException) 
        return response()->json(['error' => $exception->getMessage()], 404);
    

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

【讨论】:

以上是关于如何以 JSON 格式发送 Laravel 错误响应的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Laravel 输出的日期格式更改为 JSON?

如何将Laravel输出的日期格式更改为JSON?

如何通过ajax fetch api响应将从laravel控制器接收到的数据发送到另一个页面

如何以 json laravel 的形式返回分页

如何通过 Postman 以 JSON 格式在请求正文中发送对象数组?

以 JSON 形式返回验证错误消息 - Laravel 6