Исследование middleware в Laravel 11
Выход Laravel 11 намечен на "первый квартал" 2024 года, это может произойти уже в следующем месяце.
Я начинаю новый проект, и поскольку до релиза осталось совсем немного времени, я решил взглянуть на то, что изменится в новом крупном релизе. Я помню, как 6 месяцев назад прочитал в Laravel News статью, что Http Kernel уходит, и не придал этому особого значения.
Когда я создал проект с помощью laravel new project --dev
, я был очень удивлён тем, насколько уменьшился размер проекта. Очень удивительно было увидеть пустую папку config
(вы можете опубликовать файлы конфигурации с помощью php artisan config:publish
)!
И, конечно, никакого Http Kernel не существует. Итак… как же добавить или изменить middleware? До Laravel 11 Http Kernel (находится в app/Http/Kernel.php
) был местом, где находилась вся конфигурация для middleware. Также до Laravel 11 вы обычно не трогали bootstrap/app.php
. Однако в новой версии это уже не так.
Честно говоря, для меня, как пользователя Laravel с версии 4.2, это довольно серьёзная смена парадигмы. Вместо легко читаемого файла Kernel.php
появилось гораздо больше неявных знаний, необходимых для добавления middleware.
Новая отправная точка для bootstrap/app.php
выглядит следующим образом:
return Application::configure()
->withProviders()
->withRouting(
web: __DIR__.'/../routes/web.php',
// api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
// channels: __DIR__.'/../routes/channels.php',
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
В этом посте я просто исследую промежуточное ПО, но, как вы видите, это совсем другой подход, чем тот, который существовал раньше. Я сидел и ломал голову: "Как мне настроить собственное middleware? Как изменить настройки по умолчанию?" Чтобы выяснить это, мне пришлось изучить класс Illuminate\Foundation\Configuration\Middleware
.
Вызов Application::configure()
возвращает экземпляр Illuminate\Foundation\Configuration\ApplicationBuilder
, в котором затем вызываются различные функции, withProviders()
, withRouting()
и withMiddleware()
. Функция withMiddleware()
принимает вызываемый объект.
Используя шаблон, мы можем добавлять новые псевдонимы middleware, вызывая alias()
:
function (Middleware $middleware) {
$middleware->alias([
'some_key' => \App\Http\Middleware\MyMiddleware::class,
]);
}
После добавления some_key
мы можем назначить его отдельным маршрутам и группам маршрутов. Если мы хотим добавлять middleware в каждый запрос, мы можем использовать функции append()
или prepend()
для добавления глобального middleware.
function (Middleware $middleware) {
// Используя строку
$middleware->append(\App\Http\Middleware\MyMiddleware::class);
// Или добавить несколько
$middleware->append([
\App\Http\Middleware\MyMiddleware::class,
\App\Http\Middleware\MyOtherMiddleware::class,
]);
}
Мы можем удалить middleware, находящееся там по умолчанию, вызвав функцию remove()
.
function (Middleware $middleware) {
// ИСпользуя строку
$middleware->remove(\Illuminate\Http\Middleware\ValidatePostSize::class);
// Оли удалить несколько middleware использующихся по умолчанию
$middleware->remove([
\Illuminate\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
]);
}
Мы можем добавлять или удалять middleware в определённые группы, например, в веб-группу, используя функции appendToGroup()
/prependToGroup()
и removeFromGroup()
.
function (Middleware $middleware) {
$middleware->appendToGroup('web', \App\Http\Middleware\MyMiddleware::class);
}
Если/когда этот файл bootstrap/app.php
станет немного беспорядочным (а я представляю, что так и будет), мы можем навести порядок, перенеся всё это в вызываемый класс.
Я создал класс в app/Http
под названием AppMiddleware.php
. Поскольку старые привычки умирают, вы можете назвать его Kernel.php
…
<?php
namespace App\Http;
use Illuminate\Foundation\Configuration\Middleware;
class AppMiddleware
{
public function __invoke(Middleware $middleware)
{
$middleware->appendToGroup('web', \App\Http\Middleware\MyMiddleware::class);
}
}
Теперь в файле bootstrap/app.php
замените замыкание на новый экземпляр нашего вызываемого класса.
return Application::configure()
->withProviders()
->withRouting(
web: __DIR__.'/../routes/web.php',
// api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
// channels: __DIR__.'/../routes/channels.php',
)
->withMiddleware(new \App\Http\AppMiddleware())
->withExceptions(function (Exceptions $exceptions) {
//
Как и всё новое, перемены даются тяжело. В связи с этими переменами меня мучает один вопрос. У нас есть всё те же инструменты и возможности, но понять, как всем этим управлять, немного сложнее, по крайней мере поначалу.
Мне кажется, что это изменение потребует гораздо больше неявных знаний о встроенном middleware. Имеет ли это значение? Скорее всего, нет. Но в некоторых случаях вам может понадобиться удалить или заменить middleware по умолчанию. Это потребует от вас знания того, что есть по умолчанию. Не только в глобальном middleware, но и в группах и middleware с псевдонимами. Мне кажется, что это изменение увеличивает кривую обучения. Даже я забываю, что там есть по умолчанию или в каких псевдонимах находится, и регулярно ссылаюсь на файл app/Http/Kernel.php
.
Я задаюсь вопросом, стоит ли это того, чтобы отказаться от многословности и уменьшить размер файла?
Что вы думаете об этом новом изменении?