Роутинг, контроллеры, middleware
Маршруты, параметры, Route Model Binding, ресурсные контроллеры, middleware.
Junior Как определяются маршруты в Laravel? Какие HTTP-глаголы поддерживаются?
Маршруты — в routes/web.php (с сессиями, CSRF) и routes/api.php (stateless, префикс /api).
Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::patch(...); Route::delete(...); Route::options(...);
Route::match(['get', 'post'], '/multi', ...); // несколько глаголов
Route::any('/all', ...); // любой
Route::redirect('/old', '/new', 301);
Route::view('/about', 'pages.about'); // только шаблон
Route::fallback(fn () => ...); // если ничего не совпало
Замыкания в роутах — плохая практика для больших приложений: они ломают route:cache и размывают структуру.
Junior Как работают параметры маршрутов? Обязательные, опциональные, ограничения.
Route::get('/users/{id}', fn (int $id) => ...); // обязательный
Route::get('/users/{name?}', fn (?string $name = null) => ...); // опциональный
// Ограничения регуляркой
Route::get('/users/{id}', ...)->where('id', '[0-9]+');
Route::get('/posts/{slug}', ...)->where('slug', '[a-z0-9-]+');
// Встроенные помощники
Route::get('/users/{id}', ...)->whereNumber('id');
Route::get('/posts/{slug}', ...)->whereAlphaNumeric('slug');
// Глобальный паттерн для {id} — в RouteServiceProvider::boot()
Route::pattern('id', '[0-9]+');
Параметры приходят в контроллер как аргументы метода в порядке следования в URI.
Junior Что такое именованные маршруты и группы маршрутов?
Именованные маршруты позволяют строить URL независимо от URI:
Route::get('/users/{id}', ...)->name('users.show');
route('users.show', ['id' => 5]); // /users/5
redirect()->route('users.show', 5);
Группы — общие атрибуты для набора маршрутов:
Route::prefix('admin')
->name('admin.')
->middleware(['auth', 'admin'])
->group(function () {
Route::get('/dashboard', ...)->name('dashboard'); // admin.dashboard
Route::resource('users', AdminUserController::class);
});
Атрибуты групп комбинируются: prefix, middleware, name, namespace (legacy), domain, where.
Junior Что даёт Route::resource() и чем отличается от apiResource()?
Route::resource() регистрирует 7 RESTful-маршрутов одним вызовом:
Route::resource('posts', PostController::class);
| Метод | URI | Action | Имя |
|---|---|---|---|
| GET | /posts | index | posts.index |
| GET | /posts/create | create | posts.create |
| POST | /posts | store | posts.store |
| GET | /posts/{post} | show | posts.show |
| GET | /posts/{post}/edit | edit | posts.edit |
| PUT/PATCH | /posts/{post} | update | posts.update |
| DELETE | /posts/{post} | destroy | posts.destroy |
apiResource() — то же, но без create и edit (формы не нужны в API) — 5 маршрутов.
Ограничение набора:
Route::resource('posts', PostController::class)->only(['index', 'show']);
Route::resource('posts', PostController::class)->except(['destroy']);
Вложенные ресурсы: Route::resource('posts.comments', CommentController::class) → /posts/{post}/comments/{comment}.
Middle Что такое Route Model Binding? Явный и неявный биндинг.
Route Model Binding — автоматическое получение модели по параметру маршрута.
Неявный биндинг: имя параметра совпадает с именем переменной, тип — Eloquent-модель:
Route::get('/users/{user}', function (User $user) {
return $user; // Laravel сам сделает User::findOrFail($user)
});
Если запись не найдена — автоматически 404.
Ключ поиска по умолчанию — id. Изменить глобально:
public function getRouteKeyName(): string { return 'slug'; }
или точечно: {user:slug}.
Явный биндинг — в провайдере, с кастомной логикой:
Route::bind('user', fn (string $value) =>
User::where('slug', $value)->where('active', true)->firstOrFail());
Scoped binding {post}/{comment} — дочерняя модель ищется внутри родительской связи.
Middle Что такое middleware? Как создать своё и какие виды существуют?
Middleware — «фильтры» HTTP-запросов: код, выполняемый до/после обработчика. Примеры из коробки: auth, throttle, csrf, cors.
Виды:
- глобальные — на каждый запрос (регистрируются в
bootstrap/app.php); - группы —
web,api; - маршрутные — назначаются на конкретный роут по алиасу;
- terminable — метод
terminate()после отправки ответа (логи, метрики).
Создание:
php artisan make:middleware EnsureUserIsAdmin
public function handle(Request $request, Closure $next): Response
{
if (! $request->user()?->isAdmin()) {
abort(403);
}
return $next($request); // до — до $next; после — после
}
Регистрация (Laravel 11+, bootstrap/app.php):
->withMiddleware(function (Middleware $middleware) {
$middleware->alias(['admin' => EnsureUserIsAdmin::class]);
$middleware->appendToGroup('web', MyMiddleware::class);
})
Использование: Route::get(...)->middleware('admin'). Параметры: ->middleware('role:editor,admin').
Middle Зачем нужен route:cache и когда его нельзя использовать?
php artisan route:cache # сериализует все маршруты в bootstrap/cache/routes-*.php
php artisan route:clear
Сотни маршрутов перестают разбираться на каждый запрос → заметное ускорение (особенно с RouteServiceProvider и множеством resource).
Ограничения:
- нельзя использовать замыкания в маршрутах — их невозможно сериализовать, кэширование упадёт с ошибкой;
- после изменения роутов кэш нужно пересоздавать (включают в деплой-скрипт);
- в dev-окружении обычно не используют, чтобы не забывать сбрасывать.
Аналогично: config:cache, view:cache, event:cache — или всё сразу: php artisan optimize.