中间件构造函数无法接收请求参数,必须在handle()中通过request()->route()或$request->query()获取;参数须用冒号语法硬编码,闭包可实现动态绑定;结构化数据应存于$request->attributes。

中间件构造函数不能传请求参数,要用闭包或 request()->route() 拿
中间件实例在应用启动时就注册进管道,__construct() 里收不到 $request 或路由参数。硬塞参数进去只会报错或拿到空值。
真正能动态取值的地方只有 handle() 方法——这时请求已进来,路由已解析完成。
- 用
request()->route('id')取 URL 参数(比如/user/{id}) - 用
$request->query('sort')取查询参数 - 如果必须在注册时“绑定”某个值(如权限码),改用闭包中间件:
function ($request, $next) { return (new CustomMiddleware('admin'))->handle($request, $next); }
Laravel 10+ 中间件参数必须走「冒号语法」,且只支持字符串字面量
你在 kernel.php 里写 CustomMiddleware::class . ':admin,read' 是合法的;但写 CustomMiddleware::class . ':' . $role 会直接报错——因为中间件参数是在服务容器解析前硬编码解析的,不走 PHP 表达式求值。
- 参数以逗号分隔,全部转成字符串传入
handle()的第三个参数($parameters数组) - 例如
CustomMiddleware::class . ':user,active,7'→$parameters = ['user', 'active', '7'] - 别指望它自动转整型或布尔值,
'7'就是字符串'7'
想传对象或数组?别绕弯,用 request()->attributes 存取
中间件之间要接力传递结构化数据(比如解析后的用户配置、临时 token payload),$request->attributes 是最轻量又可靠的方式——它本质是 Symfony 的 ParameterBag,生命周期和请求一致。
- 在前置中间件里存:
$request->attributes->set('parsed_config', $configArray) - 在后续中间件或控制器里取:
$request->attributes->get('parsed_config') - 比 session、cache 或全局变量更干净,不会跨请求污染,也不触发额外 I/O
- 注意:不要存大对象或闭包,序列化可能出问题;只存数组、标量、简单 DTO
自定义中间件里调用 service 或 query DB?小心 pipeline 阻塞和重复执行
中间件在每次请求都执行,如果里面写了 User::find() 或 Cache::get(),而你又没加缓存键或条件判断,很容易变成性能黑洞。
- 确认是否真需要每次查:比如鉴权中间件查用户角色,可以先看
$request->attributes->has('user_role')再决定查不查 - DB 查询尽量复用 Eloquent model 的 already-loaded 关系,避免 N+1
- 别在中间件里调
Auth::user()后又手动查一遍用户——Laravel 的auth中间件已经做了这事,重复查等于白跑一次 SQL - 本地开发时用
php artisan debugbar:open看中间件执行次数,尤其注意 API 路由是否被 OPTIONS 预检请求反复触发
request()->attributes 或闭包封装。


















