API без версионирования — это мина замедленного действия. Сначала ты думаешь «ну у нас один эндпоинт, обойдёмся», а потом выкатываешь новую фичу и внезапно ломаешь полклиента. В Laravel версионировать API можно по-разному — от банальных префиксов v1/v2 до мудрёных middleware, которые парсят заголовки. Давай разберём, какие варианты есть и где они реально нужны.

Самый простой способ — префиксы маршрутов

Просто добавляешь v1, v2 в URL, и живёшь спокойно:

// routes/api/v1.php Route::prefix('v1')->group(function () {
    Route::get('/users', 'UserController@index');
});

// routes/api/v2.php Route::prefix('v2')->group(function () {
    Route::get('/users', 'UserController@indexV2');
});

Плюс: всё прозрачно. Минус: урлы распухают, но это терпимо.

Группы маршрутов

Когда версий становится больше, удобнее группировать:

// routes/api.php Route::group(['prefix' => 'v1', 'namespace' => 'Api\V1'], function () {
    Route::get('/users', 'UserController@index');
});

Route::group(['prefix' => 'v2', 'namespace' => 'Api\V2'], function () {
    Route::get('/users', 'UserController@index');
});

Так контроллеры не смешиваются и сразу видно, какой код к какой версии относится.

Middleware и заголовки

Более «чистый» подход — тащить версию не в URL, а в заголовке:

// app/Http/Middleware/CheckApiVersion.php public function handle($request, Closure $next)
{
    $version = $request->header('X-API-Version', '1');
    $request->attributes->set('api_version', $version);

    return $next($request);
}

В итоге у клиента один урл /users, но сервер сам решает, какую версию отдать. Красиво, но усложняет отладку и документацию.

Service Providers и DI

Для фанатов абстракций можно ещё и провайдеры прикрутить:

public function boot()
{
    $version = $this->app['request']->header('X-API-Version');
    if ($version) {
        $this->app->bind('App\Services\ApiService', function ($app) use ($version) {
            $class = "App\\Services\\ApiServiceV{$version}";
            return new $class;
        });
    }
}

Звучит умно, но на практике это стрельба из пушки по воробьям. Такой подход нужен, если у тебя реально разные реализации сервисов под каждую версию.

Что выбрать

  • Префиксы — самый надёжный вариант, идеально для публичного API.
  • Группы маршрутов — порядок в коде.
  • Middleware с заголовками — хорошо, если ты делаешь внутренний API и хочешь «чистые» урлы.
  • ServiceProvider — редкий случай, обычно оверинжиниринг.

Итог

В 90% случаев хватит простого v1/v2 в урле. Остальное — из серии «чтобы было красиво», а по факту усложняет жизнь. API должно быть предсказуемым, а не «угадайка» с заголовками.