如何设置 Laravel 中间件的执行顺序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31065936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:50:28  来源:igfitidea点击:

How to set the Laravel middleware order of execution?

phplaravellaravel-5laravel-middleware

提问by Samuel Shen

The Laravel 5 documentationdescribes two ways of assigning Middleware:

Laravel 5文档描述了分配两种方式中间件

  1. Assign middleware to the controller's route.
  2. Specify middleware within your controller's constructor.
  1. 将中间件分配给控制器的路由。
  2. 在控制器的构造函数中指定中间件。

However, I realised that any code written in the controllers __construct()function will run before the Middleware, even if the Middlewareis declared on the first line of the controller's __constructfunction.

但是,我意识到在控制器__construct()函数中编写的任何代码都将在Middleware之前运行,即使Middleware是在控制器__construct函数的第一行声明的。

I found a bug reportfor a similar issue in the Laravel github repository. However a collaborator closed the issue stating "This is the expected behaviour.".

我在 Laravel github 存储库中发现了一个类似问题的错误报告。然而,一位合作者结束了这个问题,指出“这是预期的行为。”。

I am thinking that middlewareshould be "layers" outside the application, while the __constructfunction is part of the application.

我认为middleware应该是应用程序之外的“层”,而__construct功能是应用程序的一部分。

Why is the __constructfunction executed before the middleware (given it is declared before middleware runs)? and why this is expected?

为什么__construct函数在中间件之前执行(假设它在中间件运行之前声明)?为什么这是预期的?

采纳答案by Curos

The application logic resides in the controller's methods. So basically application lives in the controller's methods, not in the whole controller itself.

应用程序逻辑驻留在控制器的方法中。所以基本上应用程序存在于控制器的方法中,而不是整个控制器本身。

Middleware runs BEFORE the request enters the respective controller method. And thus, this is always OUTSIDE the real application. No controller method is executed unless all the Middlewares are passing the request.

中间件在请求进入相应的控制器方法之前运行。因此,这始终在实际应用程序之外。除非所有中间件都在传递请求,否则不会执行任何控制器方法。

The $this->middleware("My\Middleware");statements that you put in the controller constructor, REGISTERS the My\Middlewarefor checking before the request enters the application.

$this->middleware("My\Middleware");您放在控制器构造函数中的语句,My\Middleware在请求进入应用程序之前注册用于检查。

If you see the code of a middleware and if the request is passing, then we send it to the next middleware using the $next($request);statement. This allows multiple middlewares to be executed for a single request. Now, if Laravel run the middleware right at the $this->middleware(...);statement, Laravel would probably not be able to know which middleware should be next checked.

如果您看到中间件的代码并且请求正在通过,那么我们将使用该$next($request);语句将其发送到下一个中​​间件。这允许为单个请求执行多个中间件。现在,如果 Laravel 在$this->middleware(...);语句处运行中间件,Laravel 可能无法知道接下来应该检查哪个中间件。

So, Laravel solves this by registering all the middlewares first, then passing the request through all the middlewares one by one.

所以,Laravel 通过先注册所有的中间件,然后将请求一个一个地传递给所有的中间件来解决这个问题。

回答by Bdwey

Another answer to cover another use case to that question

涵盖该问题的另一个用例的另一个答案

If it's related to the order between middleware it self

如果它与中间件之间的顺序有关它自己

You can update the $middlewarePriority in your App\Kernel.

您可以更新 App\Kernel 中的 $middlewarePriority。

回答by Raheel Hasan

They updated the order of execution between middlewares, controllerand controller's construct.

他们更新了middlewares,controller和控制器构造之间的执行顺序。

Previously it was:

以前是这样的:

1. The global middleware pipeline
2. The route middleware pipeline
3. The controller middleware pipeline

Now its:

现在它的:

1. The global middleware pipeline
2. Controller's Construct
3. The route & controller middlewares

Read more here: https://laracasts.com/discuss/channels/general-discussion/execution-order-in-controllers-constructor-whit-middlewarehttps://laravel-news.com/controller-construct-session-changes-in-laravel-5-3

在此处阅读更多信息: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

回答by Jeff Puckett

Set Middleware Priority in App\Http\Kernel

设置中间件优先级 App\Http\Kernel

For example, here I need my custom auth middleware to run first (before substitute bindings), so I unshift it onto the stack:

例如,在这里我需要首先运行我的自定义身份验证中间件(在替代绑定之前),所以我将它移到堆栈上:

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);
}

Alternatively, you could override that entire priority structure if you needed explicit control (not recommended because you'll have to pay closer attention during upgrades to see if the framework changes). Specific to this issue is the SubstituteBindingsclass that handles route model binding, so just make sure your auth middleware comes sometime before that.

或者,如果您需要显式控制,您可以覆盖整个优先级结构(不推荐,因为您必须在升级过程中密切注意以查看框架是否发生变化)。特定于这个问题的是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,
];