使用 Dingo API 快速构建 RESTful API(二)—— 编写第一个 API 接口

在一些英文文档中,我们经常会看到类似 API Endpoint 这样的术语,其实,Endpoint 就是路由的另一种表述,当我们讨论 API 时,很多人习惯将访问的 API 路由看作 Endpoint。

版本分组

为了避免和 Laravel 主应用的路由混在一起,Dingo API 使用了自己的路由器,正因如此,我们首先需要获取对应的 API 路由器实例来创建 Endpoint(可以在 routes/api.php 中定义基于 Dingo 路由器的 API 路由):

$api = app(\Dingo\Api\Routing\Router::class);

接下来需要定义 API 的版本分组,从而支持为多版本 API 接口创建同样的 Endpoint 以便后续回滚:

$api->version('v1', function ($api) {

});

如果你想要某个分组能够同时响应多个版本的 API 接口,可以传递包含多个版本号的数组到该分组:

$api->version(['v1', 'v2'], function ($api) {

});

这里基于版本号实现的分组可以看作和 Laravel 框架提供的标准路由分组一样,支持传递数组属性作为第二个参数,在这个属性数组参数中,你可以传递应用到该分组的中间件、命名空间、子域名、路由前缀等信息:

$api->version('v1', ['middleware' => 'foo'], function ($api) {

});

还可以嵌套普通的路由分组到版本分组中,以便后续实现更复杂的自定义 API Endpoint:

$api->version('v1', function ($api) {
    $api->group(['middleware' => 'foo'], function ($api) {
        // Endpoints registered here will have the "foo" middleware applied.
    });
});

创建 API 路由

有了版本号之后就可以开始使用 $api 创建 Endpoint 了:

$api->version('v1', function ($api) {
    $api->get('/task/{id}', function ($id) {
        return \App\Task::findOrFail($id);
    });
});

学院君注:这里我们基于之前构建的待办任务项目为基础进行演示。

因为 Endpoint 基于版本号进行分组,所以你可以使用同样的 URI 为同一 Endpoint 创建不同的响应:

$api->version('v1', function ($api) {
    $api->get('/task/{id}', function ($id) {
        return \App\Task::findOrFail($id);
    });
});

$api->version('v2', function ($api) {
    $api->get('/task/{id}', function ($id) {
        return \App\Task::findOrFail($id);
    });
});

在访问 Dingo API 路由之前,我们需要为其配置子域名或路由前缀,这里我们配置路由前缀为 dingoapi,在 .env 中添加如下配置项即可:

API_PREFIX=dingoapi

然后,我们就可以通过执行 php artisan api:routes 命令看到对应的 Dingo API 路由了:

Dingo API 路由

另外还有一点需要注意的是在 Dingo API 中,如果基于控制器方法定义 API 路由,需要指定完整的控制器命名空间:

$api->get('/task/{id}', \App\Http\Controllers\TaskController::class.'@show');

因为 Dingo 使用的是独立的 API 路由器,与 Laravel 内置的路由定义处理机制不同。

访问 API 路由

要访问 Dingo API,一般不会在浏览器中直接访问,因为版本号信息需要在 HTTP 请求头中指定,而不是作为 URI 的一部分,我们可以通过 Postman 来模拟 API 接口的访问:

使用Postman访问Dingo API

我们在 HTTP 请求头中通过 Accept 字段指定 API 接口对应的响应实体格式及 API 版本信息,但是这里并没有显示指定,Dingo 会使用默认的 v1 作为版本号,如果完整指定的话,这里的 Accept 字段值格式如下:

Accept: application/API_STANDARDS_TREE.API_SUBTYPE.API_VERSION+json

API_STANDARDS_TREE 配置值默认为 xAPI_SUBTYPE 默认值为空字符串,所以,如果要访问版本号为 v2 的 Dingo API 接口的话,可以这么指定 Accept 请求头:

使用Postman访问Dingo API

学院君注:Dingo API 通过 API_STANDARDS_TREEAPI_SUBTYPEAPI_VERSION 这三个字段来完整确定指定 API 的版本号,关于这三个字段可以参考上篇教程配置部分的介绍。

如果是在服务器上通过命令行访问,可以通过如下 curl 命令实现:

curl -v -H "Accept: application/x..v1+json" http://todo.test/dingoapi/task/1

对应接口返回数据如下:

使用Curl访问Dingo API

命名路由 & 生成 URL

命名路由可以帮助我们轻松生成指定路由对应的 URL。在 Dingo API 中,你可以像在 Laravel 框架中一样命名路由:

$api->version('v1', function ($api) {
    $api->get('/task/{id}', function ($id) {
        return \App\Task::findOrFail($id);
    })->name('task.detail');
});

然后就可以通过如下方式生成该路由对应的 URL:

$url = app(\Dingo\Api\Routing\UrlGenerator::class)
        ->version('v1')
        ->route('task.detail', ['id' => $id]);

必须提供一个版本号以便 URL 可以基于该版本号生成,同时,你可以在不同版本号中使用同一个命名路由。

上一篇: 使用 Dingo API 快速构建 RESTful API(一)—— 安装配置篇

下一篇: 使用 Dingo API 快速构建 RESTful API(三)—— 返回基本 JSON 响应