如何设置 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
How to set the Laravel middleware order of execution?
提问by Samuel Shen
The Laravel 5 documentationdescribes two ways of assigning Middleware:
该Laravel 5文档描述了分配两种方式中间件:
- Assign middleware to the controller's route.
- Specify middleware within your controller's constructor.
- 将中间件分配给控制器的路由。
- 在控制器的构造函数中指定中间件。
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 __construct
function.
但是,我意识到在控制器__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 middleware
should be "layers" outside the application, while the __construct
function is part of the application.
我认为middleware
应该是应用程序之外的“层”,而__construct
功能是应用程序的一部分。
Why is the __construct
function 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\Middleware
for 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
, controller
and 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 SubstituteBindings
class 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,
];