Middleware priority — the order pipeline executes
Advanced5 min read·lv-07-004
interviewlaravel-src
Concept
Middleware priority determines the execution order within a pipeline. When multiple middleware are applied to a route, they run in the order they appear in the pipeline — but some middleware must run before others regardless of route definition order.
The $middlewarePriority array (in App\Http\Kernel): Defines the relative execution order for middleware in the web and api groups. Middleware listed here runs in the declared order, regardless of how routes define them.
Why priority matters:
StartSessionmust run beforeAuthenticate, because auth needs the session to persist user state.SubstituteBindingsmust run after route matching but before controllers, so model binding works.VerifyCsrfTokenmust run after cookies are decrypted but before the request reaches the controller.
Default priority order (roughly):
HandleCorsPreventRequestsDuringMaintenanceEncryptCookiesAddQueuedCookiesToResponseStartSessionShareErrorsFromSessionAuthenticateWithBasicAuthAuthenticateThrottleRequestsSubstituteBindingsAuthorize
Custom middleware ordering: If your custom middleware depends on session or auth, ensure it runs after them by adding it at the appropriate position in $middlewarePriority.
Code Example
php
<?php
// App\Http\Kernel.php — priority array (Laravel ≤ 10)
namespace App\Http;
class Kernel extends \Illuminate\Foundation\Http\Kernel
{
protected $middlewarePriority = [
\Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
\Illuminate\Cookie\Middleware\EncryptCookies::class,
\Illuminate\Session\Middleware\StartSession::class, // session first
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class, // then auth
\Illuminate\Routing\Middleware\ThrottleRequests::class, // rate limit after auth
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class, // binding after auth
\Illuminate\Auth\Middleware\Authorize::class, // authz last
];
}
// Understanding the order with a concrete example:
// Route: ->middleware(['auth', 'verified', 'can:edit-posts'])
// 1. EncryptCookies (from web group)
// 2. StartSession (from web group — session needed for auth)
// 3. auth (Authenticate — checks session)
// 4. verified (EnsureEmailIsVerified — checks user, needs auth to run first)
// 5. can:edit-posts (Authorize — checks policy, needs auth + model binding)
// Custom middleware that needs to run AFTER session but BEFORE authorize
// Add to $middlewarePriority between StartSession and Authorize:
protected $middlewarePriority = [
// ...
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\SetUserLocale::class, // needs session (for stored locale preference)
// ...
\Illuminate\Auth\Middleware\Authorize::class,
];
// Checking middleware order in tests
// Use Route::getRoutes() to inspect which middleware are attached
// Or use Artisan: php artisan route:list --path=admin --columns=middleware