Laravel: Где использовать middleware?

Источник: «Laravel Middleware: Put in Routes, Controller, or Elsewhere? (4 Options)»
Если у вас есть Middleware, где его использовать: в файле маршрутов или в Контроллере? Рассмотрим четыре варианта.

Приведу пример поставляемого по умолчанию middleware auth, но те же принципы применимы к любому пользовательскому или Laravel Middleware классу.

Вариант 1. Файлы маршрута

Если вы читали официальную документацию Laravel по Middleware, это основной рекомендуемый способ.

Примеры:

// Одиночный маршрут
Route::get('/profile', [UserController::class, 'profile'])->middleware('auth');

// Ресурсный маршрут
Route::resource('users', UserController::class)->middleware('auth');

// Групповой маршрут
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'index']);
Route::post('/profile', [ProfileController::class, 'update']);
});

Вариант 2. Конструктор Контроллера

Это не упоминается в документации по Middleware, но в документации по Контроллерам показана такая возможность:

class UserController extends Controller
{
public function __construct()
{
// Назначить ВСЕМ методам в этом Контроллере
$this->middleware('auth');

// Назначить только ОДНОМУ методу в этом Контроллере
$this->middleware('auth')->only('create');

// Назначить только указанным методам в этом Контроллере
$this->middleware('auth')->only(['create', 'store']);

// Назначить всем методам, КРОМЕ указанных методов в Контроллере
$this->middleware('auth')->except('index');
}
}

Обратите внимание, что $this->middleware() работает, только если вы его назначает в Конструкторе. Если вы вызовите $this->middleware() из определённого метода Контроллера, он не выдаст никаких ошибок, но Middleware не будет работать.

Это вариант вполне валиден, но я предпочитаю помещать все Middleware в Маршрутах, так понятнее где искать все Middleware и не нужно прыгать Маршрутами/Контроллерами для перепроверки. Это просто привычка: всегда использовать один из способов и пусть это вас не беспокоит.

Вариант 3: Для всех файлов Маршрутов: Service Provider или Ядро (Kernel)

Существует глобальное Middleware для всех файлов Маршрутов, которое вы можете назначить в RouteServiceProvider. Фактически, Laravel уже делает это по умолчанию, взгляните на файл поставляемый с Laravel:

app/Provider/RouteServiceProvider.php:

class RouteServiceProvider extends ServiceProvider
{
public function boot()
{
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));

Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
}

Видите эти middleware('api') и middleware('web')? Таким образом можно назначить любое пользовательское Middleware любому из routes/xxxxx.php файлов.

На самом деле эти web и api не отдельные Middleware, они группа Middleware. Итак, если вы хотите, чтобы ваше Middleware выполнялось только с маршрутами wb/api, другой вариант — добавить его в массив в файле Kernel.php.

app/Http/Kernel.php:

class Kernel extends HttpKernel
{
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,

// <- Ваше middleware здесь
],

'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,

// <- Ваше middleware здесь
],
];
}

Вариант 4. Глобально в Kernel.php

Более того, вы можете назначить Middleware для выполнения каждого запроса.

Как и в предыдущем примере, Laravel по умолчанию поставляется с некоторыми из таких Middleware, их массив находится в файле app/Http/Kernel.php:

app/Http/Kernel.php:

class Kernel extends HttpKernel
{
/**
* "Эти middleware запускаются при каждом запросе к вашему приложению."
*/

protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
}

Дополнительные материалы

Предыдущая Статья

Laravel: Использование генераторов для пагинации

Следующая Статья

Laravel Pint — средство исправления стиля кода