必须使用 route::group('v1', ...) 等字面量静态前缀,禁止变量路由、accept头分发或中间件跳转,否则导致缓存失效、linux 500、ide无法跳转;命名空间、目录名、文件名、类名须严格一致且全小写;改路由或控制器后务必执行 php think route:clear。

直接用 Route::group() 配静态前缀(如 'v1'、'v2'),别搞变量路由、中间件跳转或 Accept 头自动分发——否则上线后缓存不生效、Linux 下 500、IDE 跳不到控制器,全是线上事故。
Route::group() 必须写死字符串前缀
ThinkPHP 路由缓存机制只认字面量,Route::group(config('api.version'), ...) 或 Route::group($version, ...) 看似灵活,实际会导致 php think route:clear 后仍加载旧规则,开发环境正常、上线全 404。
-
Route::group('v1', function () { ... })✅ 缓存可生成,路径匹配确定 -
Route::rule(':version/user', ...)->pattern(['version' => 'v[12]'])❌ 匹配不精准(v10会进v1)、IDE 无法跳转、Swagger 不识别版本分组 - 别在
route/app.php里重复写Route::get('v1/user', ...)和Route::get('v2/user', ...)—— 维护成本高,漏改一个就丢接口
命名空间与目录结构必须严丝合缝
路由里写的 api/v1.User/read,对应的是 app/controller/api/v1/User.php 文件,且首行必须是 namespace appcontrollerpi1;。Windows 下大小写不敏感能跑通,Linux 服务器上错一个字母就 500。
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
- 目录名必须全小写:
app/controller/api/v1/,不能是V1或v1user - 文件名必须是
User.php,不是UserController.php(除非路由里显式写api/v1.UserController/read) - 类名必须是
class User extends BaseController,不是class UserController—— 否则class_exists()检查失败 - 改完路由或控制器后,必须执行
php think route:clear,否则旧缓存还在,新规则不生效
中间件和资源层要按版本隔离,别塞进控制器
把 if ($version === 'v2') 写进控制器方法,等于亲手埋下“版本判断黑洞”:下次加 v3,就得再套一层 if;字段增减、校验开关全挤在一起,后期没人敢动。
- v1 和 v2 应该用不同服务类:
appservice1UserService和appservice2UserService,都实现同一接口 - 控制器中动态加载:
$serviceClass = "app\service\{$version}\UserService";,但务必先class_exists($serviceClass),非法版本直接返回400 Bad Request - 字段差异优先走 Resource 层:
v1UserResource和v2UserResource分别组装数据,而不是在控制器里Arr::only($data, [...])硬过滤 - 中间件必须按分组绑定:
->middleware('throttle:100,1'),不能全局注册再靠条件判断——TP 不解析路径字符串匹配中间件
别在中间件里做版本跳转或修改 input()
有人想统一拦截所有 /api/* 请求,再根据 X-API-Version 头或 ?version=v2 参数,内部重定向到不同控制器。这种做法实际踩坑极多:绕过路由缓存、破坏日志审计、和跨域/鉴权中间件顺序冲突、请求重放校验失效。
- TP 原生不支持 header 自动路由分发,所谓“Accept 版本”本质还是手动解析 + 手动传参,不是真路由匹配
- 中间件里取头要用
$request->header('x-api-version', 'v1'),别碰Accept: application/vnd.myapp.v2+json—— 正则易错、大小写不统一、性能差 - 若必须兼容老客户端,也得用中间件统一提取,并明确优先级(如
Accept > X-API-Version > ?version),但最终仍要落到静态路由分组上,不能替代Route::group() - 禁止在中间件里调用
$request->input()并修改其返回值 —— 这会污染原始请求,后续所有日志、审计、重放逻辑全乱套
最麻烦的从来不是写路由,而是命名空间大小写、文件名与类名是否一致、缓存有没有清干净——这些地方一错,错误现象毫无规律,排查起来比逻辑 bug 还耗时间。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










