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 异常。

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
贡献者:3
讨论数量: 5
发起讨论 只看当前版本


Laland
在哪个位置重写`failedValidation`和`failedAuthorization`方法?
1 个点赞 | 6 个回复 | 问答 | 课程版本 2.0.0
天使爱人间
关于 dingoapi 的 ValidationHttpException
0 个点赞 | 8 个回复 | 问答 | 课程版本 2.0.0
橙子
错误提示如何改成中文?
0 个点赞 | 3 个回复 | 问答 | 课程版本 2.0.0
clz
dingo-API form-data 格式请求参数接收
0 个点赞 | 0 个回复 | 问答 | 课程版本 2.0.0