Идёт обновление сайта. Несколько дней возможны сбои в оформлении и переводах. Документация работает — если страница выглядит сломанной, обновите её позже.

Документация
L Laravel L intervention/image
Войти

Middleware

10.x 7 мар 2026 г.

#Введение

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

Дополнительное middleware можно написать для выполнения различных задач помимо аутентификации. Например, middleware для логирования может записывать все входящие запросы в ваше приложение. В Laravel включено несколько middleware, включая middleware для аутентификации и защиты от CSRF. Все эти middleware находятся в директории app/Http/Middleware.

#Определение Middleware

Чтобы создать новое middleware, используйте Artisan-команду make:middleware:

php artisan make:middleware EnsureTokenIsValid

Эта команда создаст новый класс EnsureTokenIsValid в директории app/Http/Middleware. В этом middleware мы разрешим доступ к маршруту только если переданный параметр token совпадает с заданным значением. В противном случае пользователь будет перенаправлен на URI home:

<?php

namespace App\Http\Middleware;

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

class EnsureTokenIsValid
{
    /**
     * Обработка входящего запроса.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->input('token') !== 'my-secret-token') {
            return redirect('home');
        }

        return $next($request);
    }
}

Как видите, если переданный token не совпадает с нашим секретным токеном, middleware вернёт HTTP-перенаправление клиенту; в противном случае запрос будет передан дальше в приложение. Чтобы передать запрос дальше (разрешить прохождение middleware), нужно вызвать callback $next с аргументом $request.

Лучше всего представлять middleware как серию «слоёв», через которые HTTP-запросы должны пройти, прежде чем попасть в ваше приложение. Каждый слой может проверить запрос и даже полностью его отклонить.

Примечание

Все middleware разрешаются через service container, поэтому вы можете указывать любые зависимости в конструкторе middleware через type-hint.

#Middleware и ответы

Конечно, middleware может выполнять задачи как до, так и после передачи запроса дальше в приложение. Например, следующий middleware выполнит некоторое действие до обработки запроса приложением:

<?php

namespace App\Http\Middleware;

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

class BeforeMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        // Выполнить действие

        return $next($request);
    }
}

Однако этот middleware выполнит своё действие после обработки запроса приложением:

<?php

namespace App\Http\Middleware;

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

class AfterMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        // Выполнить действие

        return $response;
    }
}

#Регистрация Middleware

#Глобальное Middleware

Если вы хотите, чтобы middleware выполнялось при каждом HTTP-запросе к вашему приложению, добавьте класс middleware в свойство $middleware класса app/Http/Kernel.php.

#Назначение Middleware маршрутам

Если вы хотите назначить middleware конкретным маршрутам, вызовите метод middleware при определении маршрута:

use App\Http\Middleware\Authenticate;

Route::get('/profile', function () {
    // ...
})->middleware(Authenticate::class);

Вы можете назначить несколько middleware маршруту, передав массив имён middleware в метод middleware:

Route::get('/', function () {
    // ...
})->middleware([First::class, Second::class]);

Для удобства вы можете назначать псевдонимы middleware в файле app/Http/Kernel.php вашего приложения. По умолчанию свойство $middlewareAliases этого класса содержит записи для middleware, включённых в Laravel. Вы можете добавить свои middleware в этот список и назначить им псевдонимы по своему выбору:

// Внутри класса App\Http\Kernel...

protected $middlewareAliases = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

После определения псевдонима middleware в HTTP-ядре, вы можете использовать этот псевдоним при назначении middleware маршрутам:

Route::get('/profile', function () {
    // ...
})->middleware('auth');

#Исключение Middleware

При назначении middleware группе маршрутов иногда нужно исключить middleware для отдельного маршрута внутри группы. Это можно сделать с помощью метода withoutMiddleware:

use App\Http\Middleware\EnsureTokenIsValid;

Route::middleware([EnsureTokenIsValid::class])->group(function () {
    Route::get('/', function () {
        // ...
    });

    Route::get('/profile', function () {
        // ...
    })->withoutMiddleware([EnsureTokenIsValid::class]);
});

Вы также можете исключить набор middleware из всей группы определений маршрутов:

use App\Http\Middleware\EnsureTokenIsValid;

Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () {
    Route::get('/profile', function () {
        // ...
    });
});

Метод withoutMiddleware может удалять только middleware маршрутов и не применяется к глобальному middleware.

#Группы Middleware

Иногда удобно сгруппировать несколько middleware под одним ключом, чтобы проще назначать их маршрутам. Это можно сделать с помощью свойства $middlewareGroups вашего HTTP-ядра.

Laravel включает предопределённые группы middleware web и api, которые содержат общие middleware, которые вы, возможно, захотите применить к вашим веб- и API-маршрутам. Помните, что эти группы middleware автоматически применяются сервис-провайдером App\Providers\RouteServiceProvider к маршрутам в соответствующих файлах web и api:

/**
 * Группы middleware приложения.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

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

Route::get('/', function () {
    // ...
})->middleware('web');

Route::middleware(['web'])->group(function () {
    // ...
});
Примечание

Из коробки группы middleware web и api автоматически применяются к соответствующим файлам маршрутов routes/web.php и routes/api.php вашим сервис-провайдером App\Providers\RouteServiceProvider.

#Сортировка Middleware

Редко бывает нужно, чтобы middleware выполнялись в определённом порядке, но при этом вы не контролируете порядок их назначения маршруту. В этом случае вы можете указать приоритет middleware с помощью свойства $middlewarePriority в файле app/Http/Kernel.php. По умолчанию это свойство может отсутствовать в вашем HTTP-ядре. Если его нет, вы можете добавить его с приведённым ниже определением по умолчанию:

/**
 * Список middleware, отсортированных по приоритету.
 *
 * Это заставляет не-глобальное middleware всегда выполняться в заданном порядке.
 *
 * @var string[]
 */
protected $middlewarePriority = [
    \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
    \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

#Параметры Middleware

Middleware также может принимать дополнительные параметры. Например, если вашему приложению нужно проверить, что аутентифицированный пользователь имеет определённую «роль» перед выполнением действия, вы можете создать middleware EnsureUserHasRole, который принимает имя роли в качестве дополнительного аргумента.

Дополнительные параметры middleware передаются после аргумента $next:

<?php

namespace App\Http\Middleware;

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

class EnsureUserHasRole
{
    /**
     * Обработка входящего запроса.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next, string $role): Response
    {
        if (! $request->user()->hasRole($role)) {
            // Перенаправление...
        }

        return $next($request);
    }

}

Параметры middleware можно указывать при определении маршрута, разделяя имя middleware и параметры двоеточием ::

Route::put('/post/{id}', function (string $id) {
    // ...
})->middleware('role:editor');

Несколько параметров можно разделять запятыми:

Route::put('/post/{id}', function (string $id) {
    // ...
})->middleware('role:editor,publisher');

#Завершающее Middleware

Иногда middleware нужно выполнить работу после того, как HTTP-ответ был отправлен браузеру. Если вы определите метод terminate в вашем middleware и ваш веб-сервер использует FastCGI, метод terminate будет автоматически вызван после отправки ответа браузеру:

<?php

namespace Illuminate\Session\Middleware;

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

class TerminatingMiddleware
{
    /**
     * Обработка входящего запроса.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        return $next($request);
    }

    /**
     * Обработка задач после отправки ответа браузеру.
     */
    public function terminate(Request $request, Response $response): void
    {
        // ...
    }
}

Метод terminate должен принимать и запрос, и ответ. После определения завершающего middleware его нужно добавить в список маршрутов или глобальных middleware в файле app/Http/Kernel.php.

При вызове метода terminate для вашего middleware Laravel создаст новый экземпляр middleware через service container. Если вы хотите использовать один и тот же экземпляр middleware при вызове методов handle и terminate, зарегистрируйте middleware в контейнере с помощью метода singleton. Обычно это делается в методе register вашего AppServiceProvider:

use App\Http\Middleware\TerminatingMiddleware;

/**
 * Регистрация сервисов приложения.
 */
public function register(): void
{
    $this->app->singleton(TerminatingMiddleware::class);
}