Skip to main content

错误异常和错误响应

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

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

异常状态码
Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException403
Symfony\Component\HttpKernel\Exception\BadRequestHttpException400
Symfony\Component\HttpKernel\Exception\ConflictHttpException409
Symfony\Component\HttpKernel\Exception\GoneHttpException410
Symfony\Component\HttpKernel\Exception\HttpException500
Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException411
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException405
Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException406
Symfony\Component\HttpKernel\Exception\NotFoundHttpException404
Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException412
Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException428
Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException503
Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException429
Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException401
Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException415

比如,当你修改一个记录后,其他的用户已经在你之前修改了它,你可能会抛出一个 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 异常。