TP8注解路由必须安装think-annotation扩展、调用AnnotationRoute::init()初始化、配置scan路径并执行php think clear:route清缓存,缺一不可;TP6无此强制要求。

TP8注解路由必须启用扫描且手动清缓存,TP6没有这层强制要求
TP8 的注解路由不是“写了就生效”,它依赖 config/annotation.php 中的 scan 配置来决定哪些命名空间要被解析。漏配或路径写错,注解直接被忽略,且无任何提示——请求 404,你却查不到路由注册痕迹。
实操建议:
-
scan必须显式包含控制器所在命名空间,例如:['app\controller'](注意双反斜杠) - 每次修改注解(哪怕只加个
#[Middleware]),都必须执行php think clear --all,否则旧缓存残留,新注解不加载 - TP6 的注解路由虽也推荐清缓存,但未强制;TP8 下跳过这步,99% 的注解失效问题都出在这
TP8 注解语法更严格:Domain、Middleware、Validate 全部要求 #[Attribute] 形式
TP6 支持部分字符串别名写法(如 @middleware("auth")),TP8 全面废弃,所有注解必须用 PHP 8 原生属性语法,且类名需完整命名空间或已导入。
常见错误现象:
立即学习“PHP免费学习笔记(深入)”;
- 写成
@domain("admin")→ 报错Attribute "domain" does not exist - 写成
#[Domain('admin')]但没use thinknnotationDomain;→ 解析失败,静默忽略 - 在控制器方法上写
#[Validate]却没在config/validate.php中配置规则类 → 运行时报Validate class not found
正确写法示例(控制器方法):
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
#[Domain('admin')]
#[Middleware(ppmiddlewareAuth::class)]
#[Validate(ppalidateUser::class)]
public function save()
{
// ...
}
TP8 注解路由绑定到具体类/方法,不再支持 TP6 的“全局注解中间件”隐式注入
TP6 允许在 app/middleware.php 中返回注解类(如 #[Middleware]),框架会自动应用到全部请求;TP8 禁止这种写法,所有注解必须落在控制器类或方法上,否则不生效。
为什么这样改:
- 避免中间件作用域模糊,比如一个
Auth中间件该不该对/api/public生效?TP6 难以精确控制 - TP8 强调“显式优于隐式”,路由级和方法级注解可精准匹配 HTTP 方法、路径前缀、域名等条件
- IDE 和静态分析工具能真正识别注解作用范围,TP6 的全局注解无法被准确索引
迁移时最容易踩的坑:把 TP6 的 #[Middleware('cors')] 直接挪到 app/middleware.php 文件顶部 —— 它不会报错,但也不会注册任何中间件。
TP8 注解路由与传统路由共存时,优先级规则变了
TP6 中,注解路由默认在传统路由之后加载,冲突时传统路由胜出;TP8 反过来,默认注解路由优先级更高,且可通过 #[Route] 的 priority 参数显式干预。
这意味着:
- 如果你在
route/route.php里写了Route::get('user/:id', 'user/read'),又在UserController::read()上写了#[Get('api/user/:id')],TP8 会按后者匹配,前者被跳过 - 想保留传统路由优先,得给注解加
priority=0:#[Get('api/user/:id', priority: 0)] - TP6 没这个参数,
priority是 TP8 新增字段,写在 TP6 里会解析失败
复杂点在于:优先级只影响同路径下的匹配顺序,不同路径(如 /user/1 vs /api/user/1)互不干扰;但一旦路径重叠,没注意 priority,上线后可能发现某些接口突然 404 或跳转错控制器。


















