Laravel API,如何正确处理错误

Jes*_*ssy 11 api error-handling laravel

任何人都知道在Laravel中处理错误的最佳方法是什么,有什么规则可以遵循?

目前我这样做:

public function store(Request $request)
{
  $plate = Plate::create($request->all());

  if ($plate) {
    return $this->response($this->plateTransformer->transform($plate));
  } else {
    // Error handling ?
    // Error 400 bad request
    $this->setStatusCode(400);
    return $this->responseWithError("Store failed.");
  }
}
Run Code Online (Sandbox Code Playgroud)

setStatusCode和responseWithError来自我的控制器的父亲:

public function setStatusCode($statusCode)
{
    $this->statusCode = $statusCode;

    return $this;
}

public function responseWithError ($message )
{
    return $this->response([
        'error' => [
            'message' => $message,
            'status_code' => $this->getStatusCode()
        ]
    ]);

}
Run Code Online (Sandbox Code Playgroud)

但这是处理API错误的好方法,我看到一些不同的方法来处理网络上的错误,最好的是什么?

谢谢.

And*_*uro 21

默认情况下,Laravel 已经能够管理 json 响应。

无需在 app\Handler.php 中自定义渲染方法,您只需抛出一个 Symfony\Component\HttpKernel\Exception\HttpException,默认处理程序将识别请求头是否包含Accept: application/json并相应地打印 json 错误消息。

如果启用调试模式,它也会以 json 格式输出堆栈跟踪。

这是一个快速示例:

<?php

...

use Symfony\Component\HttpKernel\Exception\HttpException;

class ApiController
{
    public function myAction(Request $request)
    {
        try {
            // My code...
        } catch (\Exception $e) {
            throw new HttpException(500, $e->getMessage());
        }

        return $myObject;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是关闭调试的 Laravel 响应

{
    "message": "My custom error"
}
Run Code Online (Sandbox Code Playgroud)

这是带有调试的响应

{
    "message": "My custom error",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\HttpException",
    "file": "D:\\www\\myproject\\app\\Http\\Controllers\\ApiController.php",
    "line": 24,
    "trace": [
        {
            "file": "D:\\www\\myproject\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php",
            "line": 48,
            "function": "myAction",
            "class": "App\\Http\\Controllers\\ApiController",
            "type": "->"
        },
        {
            "file": "D:\\www\\myproject\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php",
            "line": 212,
            "function": "dispatch",
            "class": "Illuminate\\Routing\\ControllerDispatcher",
            "type": "->"
        },

        ...
    ]
}
Run Code Online (Sandbox Code Playgroud)

使用 HttpException 调用将返回您选择的 http 状态代码(在这种情况下内部服务器错误 500)

  • 不知道为什么这不是公认的答案。上面的“我的自定义错误”替换了 $e-&gt;getMessage() (3认同)

rkj*_*rkj 18

试试这个,我在我的项目中使用它(app/Exceptions/Handler.php)

public function render($request, Exception $exception)
{
    if ($request->wantsJson()) {   //add Accept: application/json in request
        return $this->handleApiException($request, $exception);
    } else {
        $retval = parent::render($request, $exception);
    }

    return $retval;
}
Run Code Online (Sandbox Code Playgroud)

现在处理Api异常

private function handleApiException($request, Exception $exception)
{
    $exception = $this->prepareException($exception);

    if ($exception instanceof \Illuminate\Http\Exception\HttpResponseException) {
        $exception = $exception->getResponse();
    }

    if ($exception instanceof \Illuminate\Auth\AuthenticationException) {
        $exception = $this->unauthenticated($request, $exception);
    }

    if ($exception instanceof \Illuminate\Validation\ValidationException) {
        $exception = $this->convertValidationExceptionToResponse($exception, $request);
    }

    return $this->customApiResponse($exception);
}
Run Code Online (Sandbox Code Playgroud)

之后自定义Api处理程序响应

private function customApiResponse($exception)
{
    if (method_exists($exception, 'getStatusCode')) {
        $statusCode = $exception->getStatusCode();
    } else {
        $statusCode = 500;
    }

    $response = [];

    switch ($statusCode) {
        case 401:
            $response['message'] = 'Unauthorized';
            break;
        case 403:
            $response['message'] = 'Forbidden';
            break;
        case 404:
            $response['message'] = 'Not Found';
            break;
        case 405:
            $response['message'] = 'Method Not Allowed';
            break;
        case 422:
            $response['message'] = $exception->original['message'];
            $response['errors'] = $exception->original['errors'];
            break;
        default:
            $response['message'] = ($statusCode == 500) ? 'Whoops, looks like something went wrong' : $exception->getMessage();
            break;
    }

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

    $response['status'] = $statusCode;

    return response()->json($response, $statusCode);
}
Run Code Online (Sandbox Code Playgroud)

始终添加Accept: application/json您的api或json请求.

  • 没有理由实现 Laravel 默认已经处理的内容,请检查我的答案 (3认同)
  • 感谢您的精彩回答!并非所有消费者都添加 `Accept` 标头,这就是为什么我检查 `$request-&gt;expectsJson() || 而不是 `$request-&gt;wantsJson()` $请求-&gt;isJson()` (2认同)

use*_*492 5

在我看来,我会保持简单。

返回带有 HTTP 错误代码和自定义消息的响应。

return response()->json(['error' => 'You need to add a card first'], 500);
Run Code Online (Sandbox Code Playgroud)

或者,如果你想抛出一个捕获的错误,你可以这样做:

   try {
     // some code
    } catch (Exception $e) {
        return response()->json(['error' => $e->getMessage()], 500);
    }
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用它来发送成功的响应:

return response()->json(['activeSubscription' => $this->getActiveSubscription()], 200);
Run Code Online (Sandbox Code Playgroud)

这样,无论哪个服务使用您的 API,它都可以期望收到相同请求的相同响应。

您还可以通过传入 HTTP 状态代码来了解它的灵活性。