中间件无法直接注入路由模型,因模型绑定发生在控制器层而非中间件执行时;需通过$request->route('key')手动获取参数,容器仅负责注入已注册服务,不参与路由参数解析。

依赖注入容器本身不负责获取路由参数,它只管“按类型或名字提供实例”。路由参数是请求上下文的一部分,必须由框架在请求生命周期中提前解析并暴露出来,容器才能配合反射去“识别”和“注入”——但这个过程不是容器主动拉取,而是框架把参数准备好后,容器用反射去匹配。
反射在参数注入中的真实角色
反射在这里干三件事:看构造函数或方法需要什么类型、查这些类型是否已在容器里注册、若没注册就尝试自动实例化。它不碰路由数据,也不解析 URL。比如你写 public function __construct(User $user),反射只告诉你“这里要一个 User 类型”,至于这个 User 实例从哪来——是容器根据绑定规则造的,还是从请求里取 ID 再查库生成的,反射不管。
- 反射读取的是 PHP 层面的类型提示(
User),不是路由里的{id} - 真正把
{id}变成User实例的,是 Laravel 的模型绑定机制,在路由解析阶段完成 - 容器拿到已准备好的
User实例后,才用反射把它们塞进构造函数或方法参数里
为什么中间件里不能直接注入路由模型
因为中间件执行时,路由还没完成模型绑定。此时 $request->route() 已存在,但 $request->route()->parameter('user') 还只是原始 ID 字符串,User $user 这种类型提示无法被满足——反射能识别类型,但容器找不到现成的 User 实例可注入。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 控制器层能注入
User,是因为框架在调用控制器方法前,已执行完路由模型绑定,并把结果存入请求对象 - 中间件的
handle方法只支持注入容器已知服务(如Request、Cache),不触发模型绑定流程 - 想在中间件用路由参数,得手动调
$request->route('id')或$request->route()->parameters()
容器如何配合路由参数完成注入
实际协作链路是:路由解析 → 提取参数 → 执行模型绑定(生成实例)→ 存入请求或全局上下文 → 容器通过反射发现方法需要某类型 → 检查该类型是否已存在(比如刚绑定好的 User)→ 直接注入。
- 绑定发生在
Route::model('user', User::class)或隐式绑定逻辑里,与容器无关 - 容器只响应“给我一个 User”这种请求,不关心这个 User 是 new 出来的、从缓存拿的,还是从路由参数查出来的
- 如果你自定义了绑定规则(如
$this->app->bind(User::class, function () { return new User(); })),容器就按这个规则给,不会去查路由
自定义参数注入的可行做法
真想让容器“理解”路由参数,得自己扩展解析逻辑。比如在容器构建参数数组前,先检查方法参数是否有特定注解(如 @RouteParam("id")),再从请求里提取对应值,转成所需类型。
- 用
ReflectionParameter查参数上的注解,而非只看类型 - 结合
$request->route()获取原始参数,再做类型转换或查询 - 这类逻辑通常放在框架的
callAction或自定义解析器中,不在基础容器内










