Урок 9: Middleware в Laravel

В 9-ом уроке мы разберем одну из ключевых тем в Laravel, это middleware. Если вы когда-либо задумывались, как добавить дополнительную логику к HTTP-запросам, например проверку прав доступа или логирование, то middleware нужно изучить. В этом уроке я подробно расскажу, как создавать и использовать middleware, работать с глобальными и роутовыми посредниками, а также обрабатывать исключения.

Что такое middleware?

Middleware (посредник) это слой, через который проходят все HTTP-запросы перед тем, как достигнуть контроллера, или после того, как ответ отправлен клиенту. Представьте себе конвейер: каждый middleware выполняет свою задачу (например, проверяет аутентификацию, логирует данные, проверяет CSRF-токен) и передает запрос дальше.

Как создать middleware?

В Laravel middleware создаются с помощью Artisan-команды. Давайте сделаем свой первый middleware для проверки роли пользователя.
Откройте терминал и выполните:

bash
php artisan make:middleware CheckRole

Эта команда создаст файл CheckRole.php в папке app/Http/Middleware. Откроем его:

php
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-токена уже там:

php
protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    // ... другие middleware
];

Важно: Глобальные middleware выполняются для каждого запроса, поэтому используйте их осторожно.

Роутовые middleware

Роутовые middleware применяются к конкретным маршрутам. Сначала зарегистрируйте их в app/Http/Kernel.php в массиве $routeMiddleware:

php
protected $routeMiddleware = [
    'role' => \App\Http\Middleware\CheckRole::class,
    'auth' => \App\Http\Middleware\Authenticate::class,
    // ... другие middleware
];

Теперь их можно использовать в маршрутах:

php
Route::get('/admin', function () {
    return 'Панель администратора';
})->middleware('role:admin');

Здесь role:admin означает, что в middleware передается параметр admin.

Пример Middleware для проверки роли

Давайте закрепим материал на примере. Допустим, мы хотим ограничить доступ к странице администратора только пользователям с ролью admin.

  1. Создаем middleware CheckRole (как в примере выше).
  2. Регистрируем его в Kernel.php.
  3. Применяем к маршруту:
php
Route::get('/admin/dashboard', 'AdminController@dashboard')
    ->middleware('role:admin');

Теперь, если пользователь не имеет роли admin, он получит ошибку 403.

Обработка исключений в middleware

Иногда в middleware могут возникать исключения (например, пользователь не авторизован). Чтобы обработать их, можно использовать метод render() в исключении или перехватить исключение в самом middleware.

Пример: Перехват исключения

Допустим, мы хотим логировать все ошибки доступа. Модифицируем CheckRole:

php
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);
}

Так мы логируем ошибку и возвращаем сообщение пользователю.

Практические задачи

Чтобы закрепить знания, выполните следующие задачи:

  1. Создайте middleware для проверки возраста
    Пользователь должен быть старше 18 лет для доступа к странице.

    php
    // Регистрация маршрута
    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);
    }
  2. Middleware для логирования запросов
    Записывайте в лог информацию о каждом запросе.

    php
    public function handle($request, Closure $next)
    {
        Log::info('Запрос к URL: ' . $request->fullUrl());
        return $next($request);
    }
  3. Проверка API-ключа
    Создайте middleware, который проверяет наличие валидного ключа в заголовках запроса.

    php
    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 для начинающих