Laravel: Где использовать 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,
];
}