使用 Dingo API 扩展包快速构建 Laravel RESTful API(七) —— 错误及异常处理

栏目: PHP · 发布时间: 5年前

内容简介:在 Dingo API 中,你可以使用响应构建器支持的多种错误方法生成错误响应:在构建 API 的时候处理异常是一件痛苦的事,在 Dingo API 中,你不需要手动构建异常响应,只需要抛出一个继承自下面是 Dingo API 内置的 Symfony 异常:

错误响应

在 Dingo API 中,你可以使用响应构建器支持的多种错误方法生成错误响应:

// 通用的错误响应,包含错误消息和状态码
return $this->response->error('404 Not Found', 404);

// 返回 404 Not Found 响应,等同于上述返回 404 状态码的错误响应
return $this->response->errorNotFound();

// 返回 401 Bad Request 响应,等同于调用 error('Bad Request', 401) 
return $this->response->errorBadRequest();

// 返回 403 Forbidden 响应,等同于调用 error('Forbidden', 403)
return $this->response->errorForbidden();

// 返回 500 Internal Error 响应,等同于调用 error('Internal Error', 500)
return $this->response->errorInternal();

// 返回 401 Unauthorized 响应,等同于调用 error('Unauthorized', 401)
return $this->response->errorUnauthorized();

// 返回 405 Method Not Allowed 响应,比如在 GET 路由上发起 POST 请求就会报这个错
return $this->response->errorMethodNotAllowed();

异常处理

异常响应

在构建 API 的时候处理异常是一件痛苦的事,在 Dingo API 中,你不需要手动构建异常响应,只需要抛出一个继承自 Symfony\Component\HttpKernel\Exception\HttpException 的异常,Dingo API 就会自动为你处理这个响应。

下面是 Dingo 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('task/{id}', function ($id) {
        $task = \App\Task::find($id);

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

        // No error, we can continue to update the user as per usual.
    });
});

我们在 Postman 中模拟发起这个 PUT 请求,并设置 last_updated 字段为小于指定任务最后更新时间的值,Dingo API 就会返回一个错误响应:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(七) —— 错误及异常处理

Dingo API 会自动捕获抛出的异常并将其转化为 JSON 格式,响应的 HTTP 状态码也会相应更改以匹配这个异常, ConflictHttpException 对应的 HTTP 状态码是 409。

资源异常

以下是资源异常,每个异常都会返回 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('tasks', function () {
        $rules = [
            'text' => ['required', 'string'],
            'is_completed' => ['required', 'boolean']
        ];

        $payload = app('request')->only('text', 'is_completed');

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

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

        // Create user as per usual.
    });
});

Dingo API 会自动捕获抛出的异常并将其转化为 JSON 格式,响应的 HTTP 状态码也会更改为与异常相匹配的值,资源异常会返回 422 状态码以及如下 JSON 格式错误信息:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(七) —— 错误及异常处理

自定义 HTTP 异常

除了 Dingo 内置支持的异常类之外,你可以创建自定义的 HTTP 异常,前提是它们继承自 Symfony\Component\HttpKernel\Exception\HttpException 基类或者实现了 Symfony\Component\HttpKernel\Exception\HttpExceptionInterface 接口。

自定义异常响应

如果你需要自定义异常返回的响应可以注册一个异常处理器(你可以在某个服务提供者如 AppServiceProviderboot 方法中添加这段代码):

app(\Dingo\Api\Exception\Handler::class)->register(function (\Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException $exception) {
    return \Illuminate\Support\Facades\Response::make(['error' => 'Hey, what do you think you are doing!?'], 401);
});

现在如果认证失败(抛出 UnauthorizedHttpException 异常)就会返回如下 JSON 格式信息:

{
    "error": "Hey, what do you think you are doing!?"
}

表单请求类

如果你要使用表单请求类,那么需要继承 Dingo API 表单请求基类 Dingo\Api\Http\FormRequest 或者完全自己实现。表单请求类会检查输入请求是否是针对当前 API 的,如果是的话,当验证失败会抛出 Dingo\Api\Exception\ValidationHttpException 异常。这个异常会被 Dingo API 渲染并返回相应的错误响应。

下面我们在 app/Http/Requests 目录下创建一个继承自 Dingo API 请求基类的表单请求类 CreateTaskRequest ,并编写其实现代码如下:

<?php

namespace App\Http\Requests;

use Dingo\Api\Http\FormRequest;

class CreateTaskRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'text' => 'required|string',
            'is_completed' => 'required|boolean'
        ];
    }
}

这样一来,我们就可以在控制器方法中声明这个表单请求类来进行表单字段验证了,编写 Api\TaskControllerstore 方法如下:

public function store(CreateTaskRequest $request)
{
    // 表单验证成功,继续后续处理
    return $this->response->errorUnauthorized();
}

在 Postman 中访问对应的路由,如果验证失败,返回错误响应如下:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(七) —— 错误及异常处理

如果你想要完全实现自己的表单请求类,则必须重写 failedValidationfailedAuthorization 方法,这些方法必须抛出上述介绍的其中一种异常而不是 Laravel 框架抛出的 HTTP 异常,感兴趣的同学可以自己去实现下,这里就不再介绍了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

浅薄

浅薄

[美]尼古拉斯·卡尔 / 刘纯毅 / 中信出版社 / 2015-11 / 49.00 元

互联网时代的飞速发展带来了各行各业效率的提升和生活的便利,但卡尔指出,当我们每天在翻看手机上的社交平台,阅读那些看似有趣和有深度的文章时,在我们尽情享受互联网慷慨施舍的过程中,我们正在渐渐丧失深度阅读和深度思考的能力。 互联网鼓励我们蜻蜓点水般地从多种信息来源中广泛采集碎片化的信息,其伦理规范就是工业主义,这是一套速度至上、效率至上的伦理,也是一套产量最优化、消费最优化的伦理——如此说来,互......一起来看看 《浅薄》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具