使用 Scramble 进行静态代码分析,自动生成 Laravel API 文档

2024 年 8 月 15 日

在 Laravel 中记录 API 通常需要使用依赖手动 PHPDoc 注释的软件包。虽然这种方法有效,但它很耗时、容易出错,并且经常导致文档随着代码库的发展而过时。

代码和文档之间的脱节可能会导致不准确的信息,从而误导开发人员并妨碍项目维护。

还可以选择手动维护 OpenAPI 规范文件,但这也会花费大量工作,而且很容易过时。

使用静态代码分析生成 API 文档

另一方面,还有静态代码分析方法。

与文档和代码可能存在分歧的传统方法不同,静态代码分析会扫描您的代码库,直接从代码中推断类型、参数和响应。这意味着,随着代码的变化,您的文档也会随之变化,从而确保两者始终保持同步,而无需开发人员付出额外努力。

例如,看一下这个简化的控制器的方法代码:

// app/Http/Controllers/Api/ExpensesController.php

public function index(Request $request)
{
    $this->authorize('readAny', Expense::class);

    $expenses = Expense::query()
        ->when(
            $request->has('category'),
            fn ($q) => $q->where('category', $request->enum('category', ExpenseCategory::class)),
        )
        ->get();

    return ExpenseResource::collection($expenses)->additional([
        'can_create' => (bool) $request->user()->can('create', Expense::class),
    ]);
}

只要看一下你就可以知道:

  • 此端点返回成功响应,其中包含费用资源集合以及显示用户是否可以创建费用的附加数据
  • 当用户未获得授权时,此端点可能会失败并出现 403 响应
  • 用户可以将费用状态传递给请求,该状态可以是可用的 ExpenseStatus 枚举值之一

这正是静态代码分析方法所做的:通过扫描代码库并推断类型,它可以确定 API 的请求和响应是什么样的,因此生成的文档始终准确并与代码库保持同步。

遇见争夺

在本文中我想向你介绍 Scramble: https://scramble.dedoc.co/

这是 Laravel 的一个软件包,它依靠静态代码分析来生成 API 文档。使用它,您无需手动编写和维护 PHPDoc 注释,并且始终拥有与您的代码库同步的最新 API 文档。

让我们通过在 Laravel API 项目中简单地要求它来安装 Scramble:

composer require dedoc/scramble

在我们检查文档之前,我想简单向你展示一下我们将记录的 API:

GET    /api/expenses
POST   /api/expenses

该应用程序是一个简单的费用跟踪器,允许用户列出所有费用并存储费用。

现在,让我们查看文档。安装 Scramble 后,可从以下位置获取 /docs/api 默认情况下。

GET /api/expenses 端点的文档

以下是 GET /api/expenses 端点,其代码我们在前面的例子中见过。

只需分析代码库,Scramble 就可以:

  • 记录此端点的成功(200)响应类型。
  • 记录用户没有权限时的错误(403)响应。
  • 记录用户未经身份验证时的错误(401)响应。
  • 记录请求的 status 参数,注意该参数是一个枚举(包括可用值)。

内部原理

让我们仔细看看它的内部工作原理。

记录成功的响应

为了确定成功响应是什么样子,Scramble 会推断控制器方法的返回类型。通过分析 ExpenseResource::collection 表达式,推理系统理解这是一个匿名的集合 ExpenseResource ,并分析了后续调用 additional ,它还知道这个集合实例中还有一个额外的数组。基于此,Scramble 可以确定响应是什么样子的。

记录 403 响应

由于调用 authorize 方法,Scramble 知道此方法可能会抛出授权异常。因此,在分析控制器方法后,我们知道了可能抛出的异常列表。由于这些异常被呈现为响应,Scramble 也会记录它们。

这也意味着你可以在控制器中抛出一些自定义异常,只要它们扩展 HttpException ,Scramble 将用正确的状态代码记录它们。

错误响应不仅可以从可能的异常中推断出来,还可以从明确的响应返回中推断出来:

return response()->json(['message' => 'You are not authorized'], 403); 

记录 401 响应

我们的应用程序的路线注册如下:

<?php

use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('expenses', App\Http\Controllers\Api\ExpensesController::class);
});

基于此,Scramble 了解到 auth 中间件,如果用户未经身份验证则返回 401 响应。

记录请求

在这个特定的例子中,Scramble 可以看到对请求中某个方法的调用,这表明有一个具有这种特定类型的参数。

此外,Scramble 还会分析验证调用以及表单请求对象上的规则列表。

对于费用创建端点,我们将编写如下验证代码:

$data = $request->validate([
    'description' => ['string'],
    'category' => ['required', Rule::enum(ExpenseCategory::class)],
    'amount' => ['required', 'integer'],
    /**
     * The date of the transaction. Will use current date when not passed.
     * @format date-time
     */
    'date' => ['date'],
]);

在这里,我们添加了 PHPDoc 注释,以手动包含请求参数的相关描述,阐明如果缺少参数 API 的行为。

生成的文档如下所示:

POST /api/expenses 端点的文档

确保文档始终是最新的

现在假设您对端点做了一些更改:您想要添加一些新的费用过滤器,返回其他附加数据,或者向类别枚举添加新的可能状态。

// app/Http/Controllers/Api/ExpensessController.php

public function index(Request $request)
{
    $this->authorize('readExpenses', Expense::class);

    $expenses = Expense::query()
        ->when(
            $request->has('category'),
            fn ($q) => $q->where('category', $request->enum('category', ExpenseCategory::class)),
        )
+       ->when(
+           $request->has('q'),
+           fn (Builder $q) => $q->where(DB::raw('lower(title)'), 'like', '%'.Str::lower($request->get('q')).'%'),
+       )
        ->get();

    return ExpenseResource::collection($expenses)->additional([
        'can_create' => (bool) $request->user()->can('createExpenses', Expense::class),
+       'can_update' => (bool) $request->user()->can('createExpenses', Expense::class),
    ]);
}

// app/Enums/ExpenseCategory.php
enum ExpenseCategory: string
{
    case Travel = 'travel';
    case Food = 'food';
+   case Utilities = 'utilities';
}

最终的文档结果如下:

更新的 GET /api/expenses 端点的文档

如您所见,文档与代码库中的所有更改保持同步。而且您只更改了代码库,而没有更改 PHPDoc 注释。

不过,PHPDoc 注释仍然很有用!当您想要为属性或请求参数添加人性化描述时,您仍然可以这样做。或者当您比 Scramble 更了解类型时,您始终可以掌控一切。

演示

这是一个使用 Scramble 进行 API 文档编写的项目的简单演示存储库。

演示文档网站: https://scramble.dedoc.co/demo/scramble#/

演示文档存储库: https://github.com/dedoc/demo-scramble

结论

在本文中,我们仔细研究了 Scramble 以及它如何简化 Laravel 项目中的 API 文档。

传统方法(例如手动编写 PHPDoc 注释或维护 OpenAPI 规范文件)既耗时又容易出错。Scramble 通过使用静态代码分析来自动更新您的文档,从而改变这一现状。

使用 Scramble,您的文档将直接反映您的代码库。当您更改 API 时,Scramble 会相应地更新文档 — 无需额外工作。

这种方法不仅节省时间,而且还能确保您的文档始终准确,减少其过时的可能性。

如果你正在开发 Laravel API 项目,不妨试试 Scramble!访问 https://scramble.dedoc.co 了解更多!


帖子 使用 Scramble 进行静态代码分析,自动生成 Laravel API 文档 首先出现在 Laravel 新闻

加入 Laravel 时事通讯 获取最新信息 类似这样的 Laravel 文章将直接发送到您的收件箱。