中间件是请求/响应的拦截与增强层,遵循PSR-15标准,通过process()或handle()方法在路由前/响应后执行横切逻辑;Laravel中需注意顺序、OPTIONS预检处理及CSRF与Session依赖关系。
PHP 中间件不是框架自带的“功能模块”,而是一种设计模式——它在 HTTP 请求 到达路由处理逻辑之前,或在 响应 发送给客户端之前,插入可复用的处理逻辑。它不替代控制器,也不直接生成页面,而是负责横切关注点(如鉴权、日志、CORS、请求解析等)。
主流 PHP 框架(Laravel、Slim、Zend Expressive、Mezzio)都基于 PSR-15 标准实现中间件接口:MiddlewareInterface::process() 接收 $request 和 $handler,必须调用 $handler->handle($re 向下传递,否则请求会中断。
quest)
实际项目中 80% 的中间件需求集中在以下三类,写法差异直接影响可维护性:
app/Http/Kernel.php 的 $middleware 数组里写 function ($request, $next) { ... return $next($request); } —— 但无法被测试、不能复用、IDE 无提示,上线前务必移出php artisan make:middleware CheckAge 生成标准类,核心是 handle() 方法;注意:$next($request) 必须被调用且只能调用一次,漏掉就卡死,多调用会重复执行后续中间件return $next($request)->withHeader(...);得先拿到响应,再操作:public function handle($request, Closure $next)
{
$startTime = microtime(true);
$response = $next($request);
$elapsed = microtime(true) - $startTime;
\Log::info('Request time', ['ms' => round($elapsed * 1000)]);
return $response;
}很多开发者照抄示例加了 Access-Control-Allow-Origin 头,但浏览器仍报错,根本原因是没覆盖预检请求(OPTIONS)路径,或未透传凭证相关头。正确做法:
立即学习“PHP免费学习笔记(深入)”;
OPTIONS 请求直接返回 200 响应,不调用 $next()
credentials: true,后端必须设 Access-Control-Allow-Credentials: true,且 Access-Control-Allow-Origin 不能为 *,得写具体域名(如 https://example.com)Illuminate\Http\Middleware\HandleCors 默认不启用,需在 app/Http/Kernel.php 的 $middleware 里显式添加,或在 cors.php 配置中打开 'supports_credentials' => true
中间件执行顺序严格依赖注册位置。例如 Laravel 中:
$middleware)最先执行,适合日志、TrustedProxy$middlewareGroups['web'])在路由匹配后、控制器前执行,适合 EncryptCookies、StartSession
Route::middleware(['auth', 'throttle:60,1']))最晚生效,但若把 auth 放在 throttle 后面,未登录用户也能触发频率限制,浪费资源VerifyCsrfToken 必须在 StartSession 之后,否则 session 未启动,CSRF token 读不到,所有 POST 表单都会 419调试时可用 php artisan route:list --middleware 查看每个路由绑定的中间件及其顺序,比猜快得多。