如何设置Laravel中间件的执行顺序?
How to set the Laravel middleware order of execution?
Laravel 5 documentation描述了两种分配Middleware的方法:
- 将中间件分配给控制器的路由。
- 在控制器的构造函数中指定中间件。
然而,我意识到在控制器 __construct()
函数中编写的任何代码都会 运行 在 中间件 之前,即使 中间件在控制器的__construct
函数的第一行声明。
我在 Laravel github 存储库中发现了一个类似问题的 bug report。然而,合作者关闭了该问题,指出 "This is the expected behaviour.".
我认为 middleware
应该 "layers" 在应用程序之外,而 __construct
函数是应用程序的一部分。
为什么 __construct
函数在中间件之前执行(假设它是在中间件 运行s 之前声明的)?为什么这是预期的?
应用程序逻辑驻留在控制器的方法中。所以基本上应用程序存在于控制器的方法中,而不是整个控制器本身。
中间件 运行s 在请求进入相应的控制器方法之前。因此,这总是在实际应用程序之外。除非所有中间件都传递请求,否则不会执行控制器方法。
您放入控制器构造函数中的 $this->middleware("My\Middleware");
语句,注册 My\Middleware
以便在请求进入应用程序之前进行检查。
如果你看到一个中间件的代码并且
如果请求通过,则我们使用 $next($request);
语句将其发送到下一个中间件。这允许为单个请求执行多个中间件。现在,如果 Laravel 运行 中间件就在 $this->middleware(...);
语句处,Laravel 可能无法知道接下来应该检查哪个中间件。
所以,Laravel通过先注册所有中间件,然后将请求一个一个地传递给所有中间件来解决这个问题。
涵盖该问题的另一个用例的另一个答案
如果与中间件之间的顺序有关,自行解决
You can update the $middlewarePriority in your App\Kernel.
他们更新了 middlewares
、controller
和控制器构造之间的执行顺序。
之前是:
1. The global middleware pipeline
2. The route middleware pipeline
3. The controller middleware pipeline
现在是:
1. The global middleware pipeline
2. Controller's 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-in-laravel-5-3
在 App\Http\Kernel
中设置中间件优先级
例如,这里我首先需要将我的自定义身份验证中间件 运行(在替换绑定之前),因此我将其取消转移到堆栈中:
public function __construct(Application $app, Router $router)
{
/**
* Because we are using a custom authentication middleware,
* we want to ensure it's executed early in the stack.
*/
array_unshift($this->middlewarePriority, MyCustomApiAuthMiddleware::class);
parent::__construct($app, $router);
}
或者,如果您需要显式控制,您可以覆盖整个优先级结构(不推荐这样做,因为您必须在升级期间密切注意框架是否发生变化)。特定于此问题的是处理路由模型绑定的 SubstituteBindings
class,因此请确保您的身份验证中间件在此之前的某个时间出现。
/**
* 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,
];
Laravel 5 documentation描述了两种分配Middleware的方法:
- 将中间件分配给控制器的路由。
- 在控制器的构造函数中指定中间件。
然而,我意识到在控制器 __construct()
函数中编写的任何代码都会 运行 在 中间件 之前,即使 中间件在控制器的__construct
函数的第一行声明。
我在 Laravel github 存储库中发现了一个类似问题的 bug report。然而,合作者关闭了该问题,指出 "This is the expected behaviour.".
我认为 middleware
应该 "layers" 在应用程序之外,而 __construct
函数是应用程序的一部分。
为什么 __construct
函数在中间件之前执行(假设它是在中间件 运行s 之前声明的)?为什么这是预期的?
应用程序逻辑驻留在控制器的方法中。所以基本上应用程序存在于控制器的方法中,而不是整个控制器本身。
中间件 运行s 在请求进入相应的控制器方法之前。因此,这总是在实际应用程序之外。除非所有中间件都传递请求,否则不会执行控制器方法。
您放入控制器构造函数中的 $this->middleware("My\Middleware");
语句,注册 My\Middleware
以便在请求进入应用程序之前进行检查。
如果你看到一个中间件的代码并且
如果请求通过,则我们使用 $next($request);
语句将其发送到下一个中间件。这允许为单个请求执行多个中间件。现在,如果 Laravel 运行 中间件就在 $this->middleware(...);
语句处,Laravel 可能无法知道接下来应该检查哪个中间件。
所以,Laravel通过先注册所有中间件,然后将请求一个一个地传递给所有中间件来解决这个问题。
涵盖该问题的另一个用例的另一个答案
如果与中间件之间的顺序有关,自行解决
You can update the $middlewarePriority in your App\Kernel.
他们更新了 middlewares
、controller
和控制器构造之间的执行顺序。
之前是:
1. The global middleware pipeline
2. The route middleware pipeline
3. The controller middleware pipeline
现在是:
1. The global middleware pipeline
2. Controller's 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-in-laravel-5-3
在 App\Http\Kernel
中设置中间件优先级
例如,这里我首先需要将我的自定义身份验证中间件 运行(在替换绑定之前),因此我将其取消转移到堆栈中:
public function __construct(Application $app, Router $router)
{
/**
* Because we are using a custom authentication middleware,
* we want to ensure it's executed early in the stack.
*/
array_unshift($this->middlewarePriority, MyCustomApiAuthMiddleware::class);
parent::__construct($app, $router);
}
或者,如果您需要显式控制,您可以覆盖整个优先级结构(不推荐这样做,因为您必须在升级期间密切注意框架是否发生变化)。特定于此问题的是处理路由模型绑定的 SubstituteBindings
class,因此请确保您的身份验证中间件在此之前的某个时间出现。
/**
* 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,
];