如何将 Laravel 错误响应发送为 JSON

How to send Laravel error responses as JSON

我刚转到 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 中实现它。

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

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

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

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

将此代码添加到 app/Exceptions/Handler.php

render 方法中
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

让我的 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());
}

编辑:Laravel 5.6 处理得很好,无需任何更改,只需确保您发送 Accept header 为 application/json.


如果你想保留状态码(这对 front-end 方理解错误类型很有用)我建议在你的 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);
}

而不是

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

使用

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

vendor\laravel\framework\src\Illuminate\Http\Concerns\InteractsWithContentTypes.php:42

public function expectsJson()
{
    return ($this->ajax() && ! $this->pjax()) || $this->wantsJson();
}

我更新了 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。

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

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

的示例
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);
}