Laravel中间件执行顺序是怎样的

wen PHP项目 1

本文目录导读:

Laravel中间件执行顺序是怎样的

  1. 核心执行顺序规则
  2. 具体执行流程
  3. 中间件定义位置与优先级
  4. 实际执行顺序示例
  5. 中间件在控制器中的执行顺序
  6. 特殊情况
  7. 实际应用建议

在 Laravel 中,中间件的执行顺序遵循“洋葱模型”或“栈”模型,即在请求进入和响应返回时,中间件按特定顺序执行。

核心执行顺序规则

全局中间件最先执行

app/Http/Kernel.php$middleware 属性中定义的中间件,会在所有路由中间件之前执行。

路由中间件按组和优先级执行

  • StartKernel(框架核心中间件)→ 全局中间件路由中间件(按注册顺序)

具体执行流程

请求进入时的执行顺序

请求 → StartKernel → 全局中间件 → 路由中间件组 → 路由特定中间件 → 控制器

响应返回时的执行顺序(反向)

控制器 → 路由特定中间件 → 路由中间件组 → 全局中间件 → StartKernel → 响应

中间件定义位置与优先级

app/Http/Kernel.php 中的三个属性

protected $middleware = [
    // 1. 全局中间件(最先执行)
    \App\Http\Middleware\TrustHosts::class,
    \App\Http\Middleware\TrustProxies::class,
    \Fruitcake\Cors\HandleCors::class,
    \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
protected $middlewareGroups = [
    'web' => [
        // 2. web 组中间件
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
    'api' => [
        // 3. api 组中间件
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];
protected $routeMiddleware = [
    // 4. 路由特定中间件(最后执行)
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

实际执行顺序示例

假设路由定义为:

Route::get('/admin', function () {
    // 控制器逻辑
})->middleware(['web', 'auth', 'admin']);

执行顺序:

StartKernel(框架核心)
2. 全局中间件(TrustHosts, TrustProxies, HandleCors...)
3. web 组中间件(EncryptCookies, StartSession...)
4. 'auth' 中间件
5. 'admin' 中间件
6. 控制器
7. 'admin' 中间件(返回时)
8. 'auth' 中间件(返回时)
9. web 组中间件(返回时)
10. 全局中间件(返回时)
11. StartKernel(返回时)

中间件在控制器中的执行顺序

如果在控制器中指定多个中间件:

public function __construct()
{
    $this->middleware('auth');
    $this->middleware('log')->only('index');
    $this->middleware('subscribed')->except('store');
}

执行顺序为:logsubscribedauth(按定义顺序的倒序执行)

特殊情况

Terminable 中间件

实现 terminate() 方法的中间件,在响应发送到浏览器后执行:

public function terminate($request, $response)
{
    // 在响应发送后执行
}

优先级(Priority)

可以设置中间件的优先级:

protected $middlewarePriority = [
    \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
];

实际应用建议

  1. 性能敏感中间件(如缓存、限流)应尽早执行
  2. 认证中间件(如 auth)应在路由组中间件之后
  3. 数据验证中间件(如 TrimStrings)应在最外层

理解这个执行顺序对于调试中间件问题、优化性能和确保安全至关重要,你可以使用 php artisan route:list 来查看每个路由的中间件执行顺序。

抱歉,评论功能暂时关闭!