编程

Laravel 11 中的 API 版本化

319 2024-08-05 21:47:00

随着 Laravel 11 的发布,其应用框架进行了精简,以删除那些不是每个项目都需要的额外文件。其中的一个改变是,在应用源码中移除所有服务提供者, AppServiceProvider 除外。

另外一个更新是,在默认安装中移除了 API 路由。如果你想在应用中添加 API。你可以通过 Artisan 命令设置 api 中间件分组及路由:

php artisan install:api

install::api 命令将生成 api.php 路由文件(并对其进行配置),用于个人访问令牌的迁移以及一个 scanctum 配置文件。如果你不需要版本化 API,这样操作就可以了。

在单独文件中版本化 API

在 Laravel 中编写版本化 API 的一种常见方法是将路由分离到不同的文件中。这样做简化了对特定 API 版本进行推理的开销,并保持了整洁。在 Laravel 10 或更早版本中,一种常见的方法是为每个 API 版本向 RouteServiceProvider 添加额外的路由文件:

$this->routes(function () {
    Route::middleware('api')
        ->prefix('api')
        ->group(base_path('routes/api.php'));
 
    Route::middleware('api')
        ->prefix('api/v1')
        ->group(base_path('routes/api_v1.php'));
 
    Route::middleware('api')
        ->prefix('api/v2')
        ->group(base_path('routes/api_v2.php'));
 
    Route::middleware('web')
        ->group(base_path('routes/web.php'));
});

上面的示例中,routes/api.php 通常为 Laravel santum 提供 /user 端点,而 API 路由的其余部分则纳入到适当的版本中。.

Laravel 11 版本化 API

将路由引导移出 RouteServiceProvider 并移到 bootstrap/app.php,这里有一些版本化 API 的一些方法。

首先,让我们生成一些文件去演示路由设置:

touch routes/api_v1.php
touch routes/api_v2.php
 
php artisan make:controller --api Api/V1/PostsController
php artisan make:controller --api Api/V2/PostsController

接下来,打开 routes/api.php 文件并将下面几行添加到文件底部:

Route::prefix('v1')->group(base_path('routes/api_v1.php'));
Route::prefix('v2')->group(base_path('routes/api_v2.php'));

上述代码位于 api.php 中意味着我们已经在 api 路由前缀内工作,并使用 api 中间件组。

接下来,让我们为每个 API 版本添加示例路由,这样我们就可以可视化每个版本的路由列表。

此处是 api_v1.php 文件:

<?php

use App\Http\Controllers\Api\V1\PostsController;

Route::apiResource('posts', PostsController::class);

以及 api_v2.php 文件:

<?php

use App\Http\Controllers\Api\V2\PostsController;

Route::apiResource('posts', PostsController::class);

路由文件定义完后,运行 route:list,我们就可以看到版本化路由。

专业提示:你可以使用 --path 标志来隔离版本化的路由,从而可以轻松地将重点放在特定的 API 版本上

php artisan route:list --path=api/v1
php artisan route:list --path=api/v2

看看如果只输出 api/v2 的路由,它有多整洁:

在应用的引导文件中定义版本化路由

我看到的另一种方法是使用 then: 参数在 bootstrap/app.php 文件中定义额外的 API 路由,该参数接受 Closure:

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
        then: function () {
            Route::middleware('api')
                ->prefix('api/v1')
                ->group(base_path('routes/api/api_v1.php'));
 
            Route::middleware('api')
                ->prefix('api/v2')
                ->group(base_path('routes/api/api_v2.php'));
        }
    )
    // ...
;

我更喜欢直接在 routes/api.php 中添加额外的路由文件,但这是另一种可行的方法。在引导文件中定义路由时,这些组没有配置为使用 api 中间件组。请确保在这些路由中包含 api 中间件组!