How to set the Laravel middleware order of execution?
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.
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.
So, Laravel solves this by registering all the middlewares first, then passing the request through all the middlewares one by one.
Set Middleware Priority in 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.
/**
* 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,
];
They updated the order of execution between middlewares
, controller
and controller's construct.
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-middleware https://laravel-news.com/controller-construct-session-changes-in-laravel-5-3
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.