Как это устроено:
Представьте конвейер. Запрос входит в приложение и проходит через цепочку middleware: один проверяет CSRF-токен, другой стартует сессию, третий смотрит, авторизован ли пользователь. Каждый слой может пропустить запрос дальше, что-то в нем поменять или оборвать обработку и сразу вернуть ответ. Готовый ответ потом идет через ту же цепочку в обратном порядке.
Вы уже пользовались middleware, даже если не заметили: проверка CSRF-токена в формах из главы 7 и редирект гостей на страницу логина из главы 8 работают именно так.
Пишем свое middleware:
Допустим, у пользователей есть булева колонка is_admin (добавили миграцией), и админка должна быть закрыта для всех остальных. Генерируем класс:
Код: Выделить всё
php artisan make:middleware EnsureUserIsAdminКод: Выделить всё
public function handle(Request $request, Closure $next): Response
{
if (! $request->user() || ! $request->user()->is_admin) {
abort(403, 'Только для администраторов');
}
return $next($request);
}Регистрация и подключение:
Начиная с Laravel 11 middleware регистрируют в bootstrap/app.php. Файла app/Http/Kernel.php в новых проектах больше нет, в Laravel 10 и старше ищите его. Дадим классу короткий псевдоним:
Код: Выделить всё
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
]);
})Код: Выделить всё
Route::middleware(['auth', 'admin'])
->prefix('admin')
->group(function () {
Route::get('/', [AdminController::class, 'index'])->name('admin.home');
Route::resource('posts', AdminPostController::class);
});Middleware умеют принимать параметры: добавьте в handle аргумент string $role и подключайте как 'role:editor'. Это спасает, когда ролей несколько и плодить отдельный класс на каждую жалко.
Из коробки пригодятся еще throttle (ограничение частоты запросов, throttle:60,1 значит 60 запросов в минуту), guest (наоборот, пускает только неавторизованных, чтобы залогиненный не видел форму входа) и verified (требует подтвержденный email).
Типичные грабли:
Забытый return перед $next($request). Метод вернет null, Laravel упадет с ошибкой про Response, а вы полчаса будете искать причину не там.
Опечатка в псевдониме или незарегистрированный alias дает ошибку "Target class [admin] does not exist". Проверяйте bootstrap/app.php первым делом.
Редирект-петля: если middleware редиректит на маршрут, который сам закрыт этим же middleware, браузер покажет ERR_TOO_MANY_REDIRECTS. Страница, куда вы уводите пользователя, должна быть открытой.
И не вешайте обычный auth на маршруты из routes/api.php: там нет сессий, для API используют auth:sanctum, до этого доберемся в главе 12.
Что усвоили:
Middleware это конвейер, через который идет каждый запрос. Мы написали свой класс, зарегистрировали псевдоним в bootstrap/app.php и закрыли группу маршрутов для не-админов. В следующей главе займемся очередями: научим приложение выполнять тяжелую работу в фоне, не заставляя пользователя ждать ответа.