在Laravel项目中自动化你的OpenAPI文档
多年来,作为开发者,我们一直在寻找能使我们的文档自动化的方法,从PHPDoc到Swagger以及其他。近年来,在API世界中出现了一个重大的转变,即采用更加以设计为先的方法来编写API文档。
这主要是由替代Swagger的OpenAPI规范的建立所刺激的。
作为开发者,我们通常没有时间或倾向于对我们的API采用设计优先的方法,这只是一个事实。
虽然这可能是最佳实践,也是大家都在说的。但在现实中,我们的工资是用来构建和交付功能的,所以我们经常跳过一些步骤。如果我告诉你,你可以在你的工作流程中增加一个小步骤,让你在工作中建立API文档,你会怎样?
让我们开始吧。在本教程中,我将建立一个完全虚构的API,没有任何目的,而且也不是我通常会建立一个API的方式。这是有原因的,因为我希望你能纯粹地关注我所采取的步骤。
我不会去看最初的设置步骤,因为这在过去已经有很多了。
在这个教程中,我将做出许多假设--主要是围绕你知道如何设置和安装Laravel,但也包括使用artisan来生成类。
我们在IDE中打开了一个Laravel项目, 我们需要添加一些功能. 我发现在构建API时,评估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();
});
}
这在一定程度上反映了谷歌图书的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规范中注册我们的路由,这总比没有好。
但是,通过一些额外的工作,我们可以记录参数和分组,使之更有意义。在Scribe中,你可以使用DocBlocks或Attributes来做这件事。
我自己更喜欢用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文档。然后,我们添加 "从API获取所有书籍",描述这个特定的端点。然后我们可以添加额外的@queryParam条目来记录这个端点的可用查询参数。这比写YAML要容易得多,对吗?
Scribe文档有更多的信息,而且你可以深入了解你所添加的信息。
我在这里只介绍了基本情况--但你已经可以看到这有多有用了。
你在API文档中使用什么?请在Twitter上告诉我们。
转:
https://laravel-news.com/automating-your-openapi-documentation
相关文章