本文目录导读:

在 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 → 响应
关键要点
-
注册顺序决定执行顺序:
- 先注册的先执行请求逻辑
- 后注册的先执行响应逻辑
-
终止中间件(Terminable):
// Laravel 中的终止中间件 class TerminateMiddleware { public function handle($request, Closure $next) { return $next($request); } // 响应发送后执行 public function terminate($request, $response) { // 日志记录、清理工作等 } } -
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;
}
}
- 请求方向:按注册顺序执行
- 响应方向:按注册逆序执行
- 核心逻辑:位于所有中间件的最内层
理解这个执行顺序,可以帮助你更好地组织中间件逻辑,
- 认证中间件应该靠前,以便后续中间件知道用户身份
- 日志中间件可以在外层捕获所有请求
- 响应格式化中间件应该在最内层
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播