Laravel 5 documentation描述了两种分配中间件的方法:
但是,我意识到在控制器__construct()
函数中编写的任何代码都将在中间件之前运行,即使在控制器的__construct
函数的第一行声明了中间件。
我在Laravel github存储库中找到了类似问题的bug report。然而,合作者关闭了该问题,声明“这是预期的行为”。
我认为middleware
应该是应用程序之外的“层”,而__construct
函数是应用程序的一部分。
为什么在中间件之前执行__construct
函数(假设它是在中间件运行之前声明的)?为什么会这样呢?
应用程序逻辑驻留在控制器的方法中。所以基本上应用程序存在于控制器的方法中,而不是整个控制器本身。
中间件在请求进入相应的控制器方法之前运行。因此,这总是在实际应用之外。除非所有中间件都在传递请求,否则不会执行任何控制器方法。
您放入控制器构造函数的$this->middleware("My\Middleware");
语句,在请求进入应用程序之前注册My\Middleware
以进行检查。
如果您看到中间件的代码并且请求是否正在通过,那么我们使用$next($request);
语句将其发送到下一个中间件。这允许为单个请求执行多个中间件。现在,如果Laravel在$this->middleware(...);
语句中运行中间件,Laravel可能无法知道下一个应该检查哪个中间件。
因此,Laravel通过首先注册所有中间件来解决这个问题,然后将请求逐个传递给所有中间件。
另一个答案是覆盖该问题的另一个用例
如果它与中间件之间的顺序有关
您可以更新App \ Kernel中的$ middlewarePriority。
他们更新了middlewares
,controller
和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
例如,在这里我需要我的自定义auth中间件首先运行(在替换绑定之前),所以我将它移到堆栈上:
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
类,因此请确保您的auth中间件在此之前的某个时间出现。
/**
* 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,
];