Как установить порядок исполнения промежуточного ПО Laravel?
Документация по Laravel 5 описывает два способа назначения Middleware:
- Назначьте промежуточное ПО на маршрут контроллера.
- Укажите промежуточное ПО в конструкторе вашего контроллера.
Однако я понял, что любой код, написанный в функции __construct()
контроллеров, будет запускаться до промежуточного программного обеспечения, даже если промежуточное программное обеспечение объявлено в первой строке функции контроллера __construct
.
Я нашел сообщение об ошибке для аналогичной проблемы в репозитории Laravel github. Однако сотрудник закрыл вопрос, заявив: "Это ожидаемое поведение".
Я думаю, что middleware
должно быть "слоями" вне приложения, в то время как функция __construct
является частью приложения.
Почему функция __construct
выполняется до промежуточного программного обеспечения (если оно объявлено до запуска промежуточного программного обеспечения)? и почему это ожидается?
Ответы
Ответ 1
Логика приложения находится в методах контроллера. Таким образом, в основном приложение работает в методах контроллера, а не во всем контроллере.
Промежуточное программное обеспечение работает до того, как запрос входит в соответствующий метод контроллера. И, таким образом, это всегда НАРУШЕНИЕ реального приложения. Никакой метод контроллера не выполняется, если все Middlewares не передают запрос.
Операторы $this->middleware("My\Middleware");
, которые вы ввели в конструктор контроллера, REGISTERS My\Middleware
для проверки до того, как запрос поступит в приложение.
Если вы видите код промежуточного программного обеспечения и
если запрос проходит, мы отправляем его на следующее промежуточное программное обеспечение с помощью инструкции $next($request);
. Это позволяет выполнять несколько промежуточных программ для одного запроса. Теперь, если Laravel запускает промежуточное программное обеспечение прямо в инструкции $this->middleware(...);
, Laravel, вероятно, не сможет узнать, какое промежуточное ПО должно быть проверено.
Итак, Laravel решает это, сначала регистрируя все средние, а затем передавая запрос через все посредники один за другим.
Ответ 2
Другой ответ, чтобы рассмотреть другой вариант использования этого вопроса
Если это связано с порядком между промежуточным программным обеспечением, оно само
Вы можете обновить $middlewarePriority в своем App\Kernel.
Ответ 3
Они обновили порядок выполнения между middlewares
, controller
и конструкцией контроллера.
Ранее это было:
1. The global middleware pipeline
2. The route middleware pipeline
3. The controller middleware pipeline
Теперь это:
1. The global middleware pipeline
2. Controller Construct
3. The route & controller middlewares
Подробнее читайте здесь: https://laracasts.com/discuss/channels/general-discussion/execution-order-in-controllers-constructor-whit-middleware https://laravel-news.com/controller-construct-session-changes -в-Laravel-5-3
Ответ 4
Установить приоритет промежуточного программного обеспечения в App\Http\Kernel
Например, здесь мне нужно, чтобы мое пользовательское промежуточное программное обеспечение для запуска было запущено первым (перед заменой привязок), поэтому я переместил его в стек:
public function __construct(Application $app, Router $router)
{
/**
* Because we are using a custom authentication middleware,
* we want to ensure it executed early in the stack.
*/
array_unshift($this->middlewarePriority, MyCustomApiAuthMiddleware::class);
parent::__construct($app, $router);
}
В качестве альтернативы вы можете переопределить всю эту структуру приоритетов, если вам нужен явный контроль (не рекомендуется, потому что вам придется уделять больше внимания во время обновлений, чтобы увидеть, изменится ли структура). Специфическим для этой проблемы является класс SubstituteBindings
который обрабатывает привязку модели маршрута, поэтому просто убедитесь, что ваше промежуточное программное обеспечение аутентификации появилось раньше.
/**
* The priority-sorted list of middleware.
*
* Forces the listed middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\App\Http\Middleware\MyCustomApiAuthMiddleware::class
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];