如何设置 Laravel 中间件的执行顺序?
Posted
技术标签:
【中文标题】如何设置 Laravel 中间件的执行顺序?【英文标题】:How to set the Laravel middleware order of execution? 【发布时间】:2015-09-12 23:31:21 【问题描述】:Laravel 5 documentation 描述了两种分配中间件的方法:
-
将中间件分配给控制器的路由。
在控制器的构造函数中指定中间件。
然而,我意识到任何写在控制器 __construct()
函数中的代码都会在 Middleware 之前运行,即使 Middleware 是在第一行声明的控制器的__construct
函数。
我在 Laravel github 存储库中找到了一个 bug report 来解决类似的问题。然而,一位合作者关闭了该问题,并指出“这是预期的行为。”。
我认为middleware
应该是应用程序之外的“层”,而__construct
函数是应用程序的一部分。
为什么__construct
函数在中间件之前执行(假设它是在中间件运行之前声明的)?为什么会出现这种情况?
【问题讨论】:
我只是做了一些测试来确认。如果您希望中间件在您的控制器__construct()
之前执行,您需要将中间件分配给路由。否则它将始终在__construct()
的末尾执行,即使分配在construct()
的第一行。
我创建了一个快速示例来概述您所描述的内容,请随时将其添加到您的问题中。 notehub.org/2015/6/26/say-we-have-a-controller----welcomecontr
@Jeemusu 感谢您的评论。是的,我还发现了两种分配中间件的方式之间的差异。但是,通过将中间件放在构造函数中执行流程的末尾,是否违反了请求生命周期(laravel.com/docs/5.1/lifecycle),因为调度请求应该在末尾?
【参考方案1】:
另一个回答该问题的另一个用例
如果它与中间件之间的顺序有关
您可以在 App\Kernel 中更新 $middlewarePriority。
【讨论】:
这应该被接受,这样我就可以命令中间件的执行 Laravel 5: laravel.com/docs/5.8/middleware#sorting-middleware ; Laravel 8(当前):laravel.com/docs/8.x/middleware#sorting-middleware【参考方案2】:应用程序逻辑驻留在控制器的方法中。所以基本上应用程序存在于控制器的方法中,而不是整个控制器本身。
中间件在请求进入相应的控制器方法之前运行。因此,这总是在真正的应用程序之外。除非所有中间件都传递请求,否则不会执行任何控制器方法。
您放入控制器构造函数中的$this->middleware("My\Middleware");
语句注册My\Middleware
用于在请求进入应用程序之前进行检查。
如果您看到中间件的代码并且
如果请求通过,那么我们使用$next($request);
语句将其发送到下一个中间件。这允许为单个请求执行多个中间件。现在,如果 Laravel 在 $this->middleware(...);
语句处运行中间件,Laravel 可能无法知道接下来应该检查哪个中间件。
所以,Laravel 解决了这个问题,首先注册所有的中间件,然后将请求一个一个地传递给所有的中间件。
【讨论】:
一个有趣的例子,中间件相对于构造函数运行。任何全局中间件实际上似乎在构造函数之前运行,而任何本地中间件在构造函数之后运行。这种不一致在过去给我带来了困惑和麻烦。 所以首先运行的原因是我不清楚答案我希望它遵循 group route => route specified (按数组顺序) 然后controler construct
。这是真的吗
我仍然对 laravel 如何决定运行它们的顺序感到困惑。它是按字母顺序排列的吗?
现在在 5.7 中,甚至全局中间件也在控制器构造之后运行!【参考方案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
类,因此请确保您的身份验证中间件在此之前的某个时间出现。
/**
* 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,
];
【讨论】:
【参考方案4】:他们更新了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
【讨论】:
以上是关于如何设置 Laravel 中间件的执行顺序?的主要内容,如果未能解决你的问题,请参考以下文章