Практические паттерны роутинга
Организация роутов по файлам
Когда роутов много, их разбивают по файлам: routes/web.php, routes/api.php, routes/admin.php. Регистрация в bootstrap/app.php:
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
Route::middleware('web')
->prefix('admin')
->name('admin.')
->group(base_path('routes/admin.php'));
},
)
Версионирование API
Route::prefix('v1')->group(function () {
Route::apiResource('posts', PostController::class);
});
Route::prefix('v2')->group(function () {
Route::apiResource('posts', PostController::class);
});
Ограничение частоты
Route::middleware('throttle:60,1')->group(function () {
Route::get('/search', fn () => 'Search');
});
60 запросов в минуту. Для API обычно больше.
Rate limit с именованными лимитерами
В AppServiceProvider:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
public function boot(): void
{
RateLimiter::for('api', function ($request) {
return Limit::perMinute(100)->by($request->user()?->id ?: $request->ip());
});
}
Fallback
Route::fallback(function () {
return response()->json(['error' => 'Not found'], 404);
});
Fallback вызывается, если ни один роут не совпал.
Роуты для SPA
Route::get('/{any}', function () {
return view('app');
})->where('any', '.*');
Ловит все пути и отдаёт один шаблон. API-роуты должны быть зарегистрированы раньше.
Health check
Route::get('/health', function () {
return response()->json(['status' => 'ok']);
});
Используется системами мониторинга и балансировщиками.
Итоги
- Роуты — это правила сопоставления URL и кода
- Группы, префиксы, middleware уменьшают дублирование
- Route Model Binding избавляет от ручного поиска моделей
- Resource-контроллеры дают CRUD по соглашению
- Form Request держит валидацию отдельно от контроллера
- Версионирование API и throttle — стандарт для продакшена