Версионирование API в Laravel 11

Источник: «API Versioning in Laravel 11»
С выходом Laravel 11 скелет приложения был урезан, чтобы удалить лишние файлы, не требующиеся в каждом проекте. Частью этого изменения стало удаление из исходного кода приложения всех сервис провайдеров, кроме AppServiceProvider.

Ещё одна часть обновлённого скелета приложения — удаление маршрутов API в инсталляции по умолчанию. Предположим, планируется добавление API в приложение или написание API исключительно с помощью Laravel. В этом случае можно настроить группу api middleware и маршруты с помощью команды Artisan:

php artisan install:api

Установка install:api создаёт файл маршрута api.php (и настраивает его), миграцию в базу данных для токенов персонального доступа и файл конфигурации sanctum. Если не нужно версионировать API, это всё, что требуется сделать.

Версионирование API в отдельных файлах

Общим подходом к написанию версионированного API в Laravel является разделение маршрутов по разным файлам. Это упрощает накладные расходы, связанные с определением конкретной версии 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 обычно предлагает конечную точку /user для Laravel sanctum, а остальные маршруты API подтягиваются к соответствующей версии.

Версионирование API в Laravel 11

Поскольку бутстраппинг маршрутов переместился из 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 middleware.

Далее добавим примеры маршрутов для каждой версии 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, мы можем увидеть версионированные маршруты!

Версионированные маршруты Laravel 11
Версионированные маршруты Laravel 11

Совет: вы можете изолировать версионированные маршруты с помощью флага --path, что позволяет сфокусироваться на конкретной версии API:

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

Посмотрите, как аккуратно всё выглядит, если просто вывести маршруты для api/v2:

Список маршрутов api/v2
Список маршрутов api/v2

Определение версионированных маршрутов в файле bootstrap/app.php

Другой подход, который встречается, — это определение дополнительных маршрутов API в файле bootstrap/app.php с помощью аргумента then:, принимающего 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 middleware. Обязательно включите группу api middleware в эти маршруты!

Дополнительные материалы

Предыдущая Статья

array_find в PHP 8.4

Следующая Статья

Создание npm пакета на TypeScript с поддержкой CommonJS и ESM