Menu

2.5. 错误异常和错误响应

创建一个 API 的时候处理错误是很痛苦的。为了避免手动的创建错误响应,你可以简单的抛出一个继承了 Symfony\Component\HttpKernel\Exception\HttpException 的异常,API 会自动的为你处理响应。

这里是 Symfony 内置的异常列表。

异常 状态码
Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException 403
Symfony\Component\HttpKernel\Exception\BadRequestHttpException 400
Symfony\Component\HttpKernel\Exception\ConflictHttpException 409
Symfony\Component\HttpKernel\Exception\GoneHttpException 410
Symfony\Component\HttpKernel\Exception\HttpException 500
Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException 411
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException 405
Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException 406
Symfony\Component\HttpKernel\Exception\NotFoundHttpException 404
Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException 412
Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException 428
Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException 503
Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException 429
Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException 401
Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException 415

比如,当你修改一个记录后,其他的用户已经在你之前修改了它,你可能会抛出一个 ConflictHttpException 异常。

$api->version('v1', function ($api) {
    $api->put('user/{id}', function ($id) {
        $user = User::find($id);

        if ($user->updated_at > app('request')->get('last_updated')) {
            throw new Symfony\Component\HttpKernel\Exception\ConflictHttpException('User was updated prior to your request.');
        }

        // 没有错误,我们可以继续按照惯例更新用户。
    });
});

这个包会自动的捕捉异常,然后转换为 JSON。响应的 HTTP 状态码也会根据异常而改变。如果你没有改变默认的错误格式, ConflictHttpException 异常将默认返回的结果为,HTTP 409 状态码和响应的 JSON 表述 。

{
    "message": "User was updated prior to your request.",
    "status_code": 409
}

资源异常

下面是通用的资源异常的列表,它们都会返回 HTTP 422 状态码。

Dingo\Api\Exception\DeleteResourceFailedException
Dingo\Api\Exception\ResourceException
Dingo\Api\Exception\StoreResourceFailedException
Dingo\Api\Exception\UpdateResourceFailedException

这些异常是特殊的,因为它们允许你传递任何验证错误,当你尝试去创建、更新或者删除资源的时候。

举一个例子,当你尝试验证新用户的创建时遇到错误时,你可能会抛出StoreResourceFailedException

$api->version('v1', function ($api) {
    $api->post('users', function () {
        $rules = [
            'username' => ['required', 'alpha'],
            'password' => ['required', 'min:7']
        ];

        $payload = app('request')->only('username', 'password');

        $validator = app('validator')->make($payload, $rules);

        if ($validator->fails()) {
            throw new Dingo\Api\Exception\StoreResourceFailedException('Could not create new user.', $validator->errors());
        }

        // 按照惯例创建用户。
    });
});

这个包会自动的捕获这些异常,转换为 JSON 的表述。响应的 HTTP 状态码也会根据异常而改变。资源异常返回的结果为 HTTP 422 状态码和响应的 JSON 表述。

{
    "message": "Could not create new user.",
    "status_code": 422,
    "errors": {
        "username": [
            "The username field is required."
        ],
        "password": [
            "The password field is required."
        ]
    }
}

自定义 HTTP 异常

你可以创建你自己的 HTTP 异常,只要它们继承了 Symfony\Component\HttpKernel\Exception\HttpException 或者实现了 Symfony\Component\HttpKernel\Exception\HttpExceptionInterface 接口。

自定义异常响应

如果你需要自定义异常的响应,你可以注册一个自定义错误 handler。

app('Dingo\Api\Exception\Handler')->register(function (Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException $exception) {
    return Response::make(['error' => 'Hey, 你这是要干嘛!?'], 401);
});

现在如果验证错误,我们会用下面的 JSON 表述呈现。

{
    "error": "Hey, 你这是要干嘛!?"
}

表单请求

如果你正在使用表单请求,那么你不仅需要继承基本的 API 表单请求类,还需要实现你自己的。基础 API 表单请求类将会
检查传入的请求是否用于 API,如果是,当验证失败时将抛出 Dingo\Api\Exception\ValidationHttpException 异常。

这个异常将会被正确的渲染,然后返回错误响应。

如果你喜欢实现自己的表单请求,你 必须 重写 failedValidationfailedAuthorization 方法。这些方法 必须 抛出上面提到的异常中的一个,而且不是 Laravel 抛出的 HTTP 异常。

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 0
发起讨论


暂无话题~
刻意练习,每日精进。
5
点赞
2740
浏览
0
讨论
译者