Урок 09

Middleware

Middleware — это слой обработки между запросом и контроллером. Middleware может проверить аутентификацию, залогировать запрос, добавить заголовки, ограничить частоту запросов.

Как работает

Запрос проходит через цепочку middleware. Каждый может:

  • Пропустить запрос дальше через $next($request)
  • Прервать и вернуть свой ответ
  • Изменить запрос или ответ

Создание

php artisan make:middleware CheckAge
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckAge
{
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->age < 18) {
            return redirect('/home');
        }

        return $next($request);
    }
}

Регистрация алиаса

В bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'age' => \App\Http\Middleware\CheckAge::class,
    ]);
})

Применение

К роуту

Route::get('/adult', fn () => 'OK')->middleware('age');

К группе

Route::middleware(['auth', 'age'])->group(function () {
    Route::get('/dashboard', fn () => 'Dashboard');
});

В контроллере

public function __construct()
{
    $this->middleware('auth');
}

Встроенные middleware

  • auth — требует аутентификации
  • auth:sanctum — токен Sanctum
  • guest — только для неавторизованных
  • verified — email подтверждён
  • throttle:60,1 — не больше 60 запросов в минуту
  • can:update,post — проверка прав через Policy

Параметры

public function handle(Request $request, Closure $next, string $role): Response
{
    if (!$request->user()->hasRole($role)) {
        abort(403);
    }

    return $next($request);
}

Применение:

Route::get('/admin', fn () => 'Admin')->middleware('role:admin');

Группы middleware

В bootstrap/app.php:

$middleware->group('admin', [
    'auth',
    'role:admin',
]);

Применение:

Route::middleware('admin')->group(...);

После ответа

Middleware может выполнить код после того, как контроллер вернул ответ:

$response = $next($request);

// логирование

return $response;

Terminate

Для выполнения кода после отправки ответа клиенту:

public function terminate(Request $request, Response $response): void
{
    //
}