自动化你的 OpenAPI 文档

发布时间:作者:

Automating your OpenAPI Documentation image

多年来,作为开发者,我们一直在寻找自动化文档的方法,从 PHPDoc 到 Swagger 等等。近年来,API 世界发生了重大转变,开始采用以设计为主导的 API 文档方法。这主要得益于 OpenAPI 规范的创建,它是 Swagger 的替代方案。

作为开发者,我们往往没有时间或兴趣深入研究 API 的设计优先方法 - 事实就是这样。虽然这可能是最佳实践,也是每个人都在说的话。但现实情况是,我们被付钱来构建和发布功能,因此我们经常跳过一些步骤。如果我说你可以将一个小的步骤添加到你的工作流程中,让你可以边走边构建 API 文档,你会相信吗?

让我们开始吧。在本教程中,我将构建一个完全虚构的 API,没有目的,它也不是我通常构建 API 的方式。这样做是有原因的,因为我希望你专注于我采取的步骤。

我不会介绍初始设置步骤,因为之前已经介绍过很多次。在本教程中,我将做出很多假设 - 主要围绕你是否知道如何设置和安装 Laravel,以及如何使用 artisan 生成类。

我们在 IDE 中打开了一个 Laravel 项目,我们需要添加一些功能。我发现,在构建 API 时,评估 API 的目的非常有用。试着理解为什么要构建它,以及它是为谁构建的。这将帮助我们了解什么对我们的 API 有用,并避免添加一些不必要的端点。

在本教程中,我们将构建一个简单的书架 API。它将允许我们创建一些非常基本的功能 - 这样我们就有一个构建目标。这个 API 的目标用户是那些可以连接到我们的 API 来管理书籍的用户。对这些用户来说,最重要的功能是查看书籍和快速添加书籍。最终会有其他功能可用,但始终要从每个用户都需要的主要功能开始。

为 Book 模型创建一个新的模型、迁移和工厂。这将是我们 API 中的主要模型。你想要在这个模型上添加的属性对于本教程来说并不重要 - 但我还是会介绍一下。

public function up(): void
{
Schema::create('books', static function (Blueprint $table): void {
$table->id();
 
$table->string('title');
$table->string('subtitle')->nullable();
$table->text('description');
$table->string('language');
 
$table->unsignedBigInteger('pages');
 
$table->json('authors');
$table->json('categories');
$table->json('images');
$table->json('isbn');
 
$table->date('published_at');
$table->timestamps();
});
}

这在一定程度上反映了 Google Books API。我们有一个书籍标题和副标题,即书籍的名称。描述和语言说明了书籍的主题和使用语言。我们有一个页数来查看它是否是一本厚重的书。然后我们有作者、类别、图片和 ISBN 来添加更多信息。最后,还有出版日期。

现在我们有了模型和数据库,我们可以开始研究 API 本身。我们的第一步是安装一个包,让我们能够生成 API 文档。有一个很棒的包叫 Scribe 你可以用它,它在 Laravel 和简单的 PHP 应用程序中都有效。你可以使用以下 composer 命令来安装它

composer require --dev knuckleswtf/scribe

安装完成后,你可以按照设置说明在你的应用程序中使其正常工作。安装完成后并发布配置后,你可以对 API 文档生成进行测试运行,以确保其按预期工作。你应该能够在开箱即用时获得类似这样的结果

openapi: 3.0.3
info:
title: Laravel
description: ''
version: 1.0.0
servers:
-
url: 'http://localhost:8000'
paths: []
tags: []

现在我们知道它能够正常工作了,我们可以添加一些路由来确保它们被用于 OpenAPI 生成中。

让我们从围绕获取书籍、获取书籍列表和获取单个书籍的第一个路由开始。

Route::prefix('books')->as('books:')->middleware(['api'])->group(static function (): void {
Route::get(
'/',
App\Http\Controllers\Api\Books\IndexController::class,
)->name(
name: 'index',
);
 
Route::get(
'{book}',
App\Http\Controllers\Api\Books\ShowController::class,
)->name(
name: 'show',
);
});

我们在 books 前缀下有两个路由,它们都是 GET 路由,不需要身份验证。这些将是任何人都可以访问的公共 API 的一部分。

现在我们已经有了路由和控制器,我们需要考虑如何处理这些路由。我们希望能够排序和过滤请求,以便我们可以请求特定的书籍列表。为了实现这一点,我们将使用 Spatie Laravel Query Builder 包,它提供了一个干净的界面来搜索和过滤我们需要的内容。让我们使用以下 composer 命令来安装它

composer require spatie/laravel-query-builder

安装完成后,我们就可以考虑如何过滤 API 请求以获取正确的书籍列表。所有优秀的 API 都需要分页。为了实现这一点,我们可以使用 Laravel 的内置分页器。然而,Aaron Francis 创建了一个名为 Fast Paginate 的分页器,它的性能更高 - 这对于 API 来说非常重要。你可以使用以下 composer 命令安装它

composer require hammerstone/fast-paginate

让我们将这两者结合起来,以便我们可以构建一个集合并返回一个分页结果。

return QueryBuilder::for(
subject: Book::class,
)->allowedFilters(
filters: ['language', 'pages', 'published_at'],
)->fastPaginate();

这对我们的用例来说效果很好 - 但是,我不喜欢直接从 API 返回查询结果。我们应该始终使用 API 资源将响应转换为可控的格式。Laravel 有内置的资源,或者你可以使用 PHP Leagues Fractal 包,它非常不错。在这个例子中,我将使用一个我之前 写过 的包,所以我不会详细介绍。最终,我们应该得到一个类似以下内容的控制器,或者至少与它非常相似

final class IndexController
{
public function __invoke(Request $request): JsonResponse
{
return new JsonResponse(
data: BookResource::collection(
resource: QueryBuilder::for(
subject: Book::class,
)->allowedFilters(
filters: ['language', 'pages', 'published_at'],
)->fastPaginate(),
),
);
}
}

到目前为止,这只会将我们的路由注册到 OpenAPI 规范中,这比没有好。但是,通过一些额外的努力,我们可以记录参数并将事物分组,从而使 API 文档更有意义。在 Scribe 中,你可以使用 DocBlocks 或属性来做到这一点。我自己更喜欢使用 DocBlocks,因为并非所有你想要使用的字段都有属性。让我给你举个例子,我将逐步介绍我所做的一切。

final class IndexController
{
/**
* @group Book Collection
*
* Get all Books from the API.
*
* @queryParam filter[language] Filter the books to a specific language. filter[language]=en
* @queryParam filter[pages] Filter the books to those with a certain amount of pages. filter[pages]=1000
* @queryParam filter[published_at] Filter the books to those published on a certain date. filter[published_at]=12-12-1992
*
*/
public function __invoke(Request $request): JsonResponse
{
return new JsonResponse(
data: BookResource::collection(
resource: QueryBuilder::for(
subject: Book::class,
)->allowedFilters(
filters: ['language', 'pages', 'published_at'],
)->fastPaginate(),
),
);
}
}

我们首先添加 @group Book Collection,它将把这个端点分组到一个 "Book Collection" 下,从而更轻松地导航你的 API 文档。然后我们添加 "Get all Books from the API.",它描述了特定的端点。然后我们可以添加额外的 @queryParam 条目来记录这个端点接受的可用查询参数。这比编写 YAML 方便多了,对吧!

Scribe 文档提供了更多信息,你可以深入了解添加的信息。我在这里只介绍了基础知识 - 但你已经可以看到它有多有用。你使用什么工具来编写 API 文档?在 Twitter 上告诉我们吧!

Steve McDougall photo

技术作家, Laravel 新闻,开发者倡导者,Treblle。API 专家,经验丰富的 PHP/Laravel 工程师。 YouTube 直播主.

Cube

Laravel 新闻通讯

加入 40k+ 其他开发者,绝不错过新的技巧、教程等等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

没有妥协

Joel 和 Aaron 是来自 No Compromises 播客的两位经验丰富的开发者,现在可以为您的 Laravel 项目雇用他们。 ⬧ 固定费用 7500 美元/月。 ⬧ 没有冗长的销售流程。 ⬧ 没有合同。 ⬧ 100% 返款保证。

没有妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

运行旧版本的 Laravel?立即使用自动化 Laravel 升级和代码现代化来保持应用程序更新。

Shift
Bacancy logo

Bacancy

用经验丰富的 Laravel 开发人员为您的项目充电,他们拥有 4-6 年的经验,每月只需 2500 美元。获取 160 小时的专用专业知识和 15 天的无风险试用。立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

现在就获得幸运 - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。一个开源软件包,它将现代无头电子商务功能的强大功能带到 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 工作板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动套件

SaaSykit 是一个 Laravel SaaS 启动套件,它包含运行现代 SaaS 所需的所有功能。付款、精美结帐、管理面板、用户仪表板、身份验证、就绪组件、统计信息、博客、文档等等。

SaaSykit: Laravel SaaS 启动套件
Rector logo

Rector

您无缝升级 Laravel、降低成本和加速创新的合作伙伴,为成功公司提供服务

Rector
MongoDB logo

MongoDB

通过将 MongoDB 和 Laravel 强大地集成到您的 PHP 应用程序中,使开发人员能够轻松高效地构建应用程序。支持事务性、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。了解 MongoDB 的灵活、现代数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel 提示构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 软件包为您的 Laravel 应用程序添加评论

阅读文章