В 9-ом уроке мы разберем одну из ключевых тем в Laravel, это middleware. Если вы когда-либо задумывались, как добавить дополнительную логику к HTTP-запросам, например проверку прав доступа или логирование, то middleware нужно изучить. В этом уроке я подробно расскажу, как создавать и использовать middleware, работать с глобальными и роутовыми посредниками, а также обрабатывать исключения.
Что такое middleware?
Middleware (посредник) это слой, через который проходят все HTTP-запросы перед тем, как достигнуть контроллера, или после того, как ответ отправлен клиенту. Представьте себе конвейер: каждый middleware выполняет свою задачу (например, проверяет аутентификацию, логирует данные, проверяет CSRF-токен) и передает запрос дальше.
Как создать middleware?
В Laravel middleware создаются с помощью Artisan-команды. Давайте сделаем свой первый middleware для проверки роли пользователя.
Откройте терминал и выполните:
php artisan make:middleware CheckRole
Эта команда создаст файл CheckRole.php
в папке app/Http/Middleware
. Откроем его:
namespace App\Http\Middleware; use Closure; class CheckRole { public function handle($request, Closure $next, $role) { // Проверяем, авторизован ли пользователь if (!auth()->check()) { return redirect()->route('login'); } // Проверяем роль пользователя if (auth()->user()->role !== $role) { abort(403, 'Доступ запрещен'); } return $next($request); } }
Здесь:
handle()
— метод, обрабатывающий запрос.$next($request)
— передает запрос следующему middleware или контроллеру.$role
— параметр, который мы можем передать в middleware (например, ‘admin’).
Глобальные и роутовые middleware
Middleware в Laravel делятся на два типа: глобальные (применяются ко всем запросам) и роутовые (применяются к конкретным маршрутам или группам).
Глобальные middleware
Чтобы зарегистрировать middleware глобально, добавьте его в массив $middleware
в файле app/Http/Kernel.php
. Например, middleware для проверки CSRF-токена уже там:
protected $middleware = [ \App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\CheckForMaintenanceMode::class, // ... другие middleware ];
Важно: Глобальные middleware выполняются для каждого запроса, поэтому используйте их осторожно.
Роутовые middleware
Роутовые middleware применяются к конкретным маршрутам. Сначала зарегистрируйте их в app/Http/Kernel.php
в массиве $routeMiddleware
:
protected $routeMiddleware = [ 'role' => \App\Http\Middleware\CheckRole::class, 'auth' => \App\Http\Middleware\Authenticate::class, // ... другие middleware ];
Теперь их можно использовать в маршрутах:
Route::get('/admin', function () { return 'Панель администратора'; })->middleware('role:admin');
Здесь role:admin
означает, что в middleware передается параметр admin
.
Пример Middleware для проверки роли
Давайте закрепим материал на примере. Допустим, мы хотим ограничить доступ к странице администратора только пользователям с ролью admin
.
- Создаем middleware
CheckRole
(как в примере выше). - Регистрируем его в
Kernel.php
. - Применяем к маршруту:
Route::get('/admin/dashboard', 'AdminController@dashboard') ->middleware('role:admin');
Теперь, если пользователь не имеет роли admin
, он получит ошибку 403.
Обработка исключений в middleware
Иногда в middleware могут возникать исключения (например, пользователь не авторизован). Чтобы обработать их, можно использовать метод render()
в исключении или перехватить исключение в самом middleware.
Пример: Перехват исключения
Допустим, мы хотим логировать все ошибки доступа. Модифицируем CheckRole
:
public function handle($request, Closure $next, $role) { try { if (auth()->user()->role !== $role) { throw new \Exception('Недостаточно прав'); } } catch (\Exception $e) { Log::error($e->getMessage()); abort(403, $e->getMessage()); } return $next($request); }
Так мы логируем ошибку и возвращаем сообщение пользователю.
Практические задачи
Чтобы закрепить знания, выполните следующие задачи:
- Создайте middleware для проверки возраста
Пользователь должен быть старше 18 лет для доступа к странице.// Регистрация маршрута Route::get('/club', function () { return 'Добро пожаловать в клуб!'; })->middleware('age:18'); // Метод handle() в middleware public function handle($request, Closure $next, $age) { if ($request->user()->age < $age) { abort(403, 'Вам еще рано сюда!'); } return $next($request); }
- Middleware для логирования запросов
Записывайте в лог информацию о каждом запросе.public function handle($request, Closure $next) { Log::info('Запрос к URL: ' . $request->fullUrl()); return $next($request); }
- Проверка API-ключа
Создайте middleware, который проверяет наличие валидного ключа в заголовках запроса.public function handle($request, Closure $next) { if ($request->header('X-API-KEY') !== config('app.api_key')) { abort(401, 'Неверный API-ключ'); } return $next($request); }
Middleware это мощный инструмент в Laravel, позволяющий гибко управлять HTTP-запросами. Вы научились создавать посредников, применять их глобально или к отдельным маршрутам, а также обрабатывать исключения.
Хотите изучить Laravel от А до Я? Полный курс по Laravel для начинающих