PHP 中间件执行顺序

wen PHP项目 1

本文目录导读:

PHP 中间件执行顺序

  1. 核心执行原理
  2. 具体实现示例
  3. 常见框架的执行顺序
  4. 关键要点
  5. 调试技巧

在 PHP 中间件中,执行顺序遵循洋葱模型(Onion Model)或管道模型,理解这个顺序对于正确处理请求和响应至关重要。

核心执行原理

中间件的执行顺序是:先进先出(FIFO)处理请求,后进先出(LIFO)处理响应

// 假设有中间件 A、B、C,注册顺序为 A → B → C
// 执行流程如下:
请求 → A(前) → B(前) → C(前) → 控制器/核心逻辑 → C(后) → B(后) → A(后) → 响应

具体实现示例

Laravel 框架示例

// 在 Kernel.php 中
protected $middleware = [
    \App\Http\Middleware\A::class,
    \App\Http\Middleware\B::class,
    \App\Http\Middleware\C::class,
];
// 每个中间件的 handle 方法
class A {
    public function handle($request, Closure $next)
    {
        // 请求到达时的处理(前)
        echo "A-开始 ";
        // 传递给下一个中间件
        $response = $next($request);
        // 响应返回时的处理(后)
        echo "A-结束 ";
        return $response;
    }
}
// 输出结果:
// A-开始 B-开始 C-开始 核心逻辑 C-结束 B-结束 A-结束

手动实现中间件管道

class MiddlewarePipeline
{
    private $middlewares = [];
    public function add($middleware)
    {
        $this->middlewares[] = $middleware;
    }
    public function handle($request)
    {
        // 使用 array_reduce 构建调用链
        $core = function($request) {
            echo "核心逻辑 ";
            return "响应";
        };
        $pipeline = array_reduce(
            array_reverse($this->middlewares),
            function($next, $middleware) {
                return function($request) use ($next, $middleware) {
                    return $middleware->handle($request, $next);
                };
            },
            $core
        );
        return $pipeline($request);
    }
}
// 使用示例
$pipeline = new MiddlewarePipeline();
$pipeline->add(new MiddlewareA());
$pipeline->add(new MiddlewareB());
$pipeline->add(new MiddlewareC());
$result = $pipeline->handle($request);

常见框架的执行顺序

Laravel 中间件优先级

// Laravel 中的执行顺序(从外到内)
1. Global Middleware(全局中间件)
2. Group Middleware(组中间件,如 web、api)
3. Route Middleware(路由中间件)
4. Controller Middleware(控制器中间件)

Slim 框架示例

// Slim 4 中间件执行顺序
$app->add(new MiddlewareA());  // 最先执行
$app->add(new MiddlewareB());  // 第二个执行
$app->add(new MiddlewareC());  // 第三个执行
// 实际执行顺序
// 请求 → A → B → C → 路由处理 → C → B → A → 响应

关键要点

  1. 注册顺序决定执行顺序

    • 先注册的先执行请求逻辑
    • 后注册的先执行响应逻辑
  2. 终止中间件(Terminable)

    // Laravel 中的终止中间件
    class TerminateMiddleware
    {
     public function handle($request, Closure $next)
     {
         return $next($request);
     }
     // 响应发送后执行
     public function terminate($request, $response)
     {
         // 日志记录、清理工作等
     }
    }
  3. CSRF 保护的特殊性

    // CSRF 中间件通常位于 Web 中间件组的最外层
    protected $middlewareGroups = [
     'web' => [
         \App\Http\Middleware\EncryptCookies::class,
         \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
         \Illuminate\Session\Middleware\StartSession::class,
         // CSRF 检查在 Session 之后
         \Illuminate\View\Middleware\ShareErrorsFromSession::class,
         \App\Http\Middleware\VerifyCsrfToken::class,
     ],
    ];

调试技巧

// 在中间件中添加日志
class DebugMiddleware
{
    public function handle($request, Closure $next)
    {
        \Log::info('中间件开始: ' . get_class($this));
        $response = $next($request);
        \Log::info('中间件结束: ' . get_class($this));
        return $response;
    }
}
  • 请求方向:按注册顺序执行
  • 响应方向:按注册逆序执行
  • 核心逻辑:位于所有中间件的最内层

理解这个执行顺序,可以帮助你更好地组织中间件逻辑,

  • 认证中间件应该靠前,以便后续中间件知道用户身份
  • 日志中间件可以在外层捕获所有请求
  • 响应格式化中间件应该在最内层

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