yii框架api版本控制必须使用显式模块(如apiv1)而非仅配路由,因模块提供命名空间、配置隔离与行为绑定等天然隔离能力;路由前缀(v1/)须与模块id(apiv1)错开,避免自动加载冲突,并需严格分离迁移、模型、认证等版本相关配置。

Yii 框架本身不内置版本控制机制,直接把 v1 当模块 ID 或硬塞进路由规则里,90% 的项目会在半年后遇到路由冲突、控制器错绑、迁移混乱这三类问题。
为什么用 modules 而不是单纯配路由规则
模块(Module)是 Yii 天然的隔离单元,它自带命名空间、配置作用域、行为绑定和权限上下文。如果你只在 urlManager.rules 里加 'v1/<controller:>' => 'v1/<controller>'</controller></controller:>,而没建真正的 v1 模块,那么:
- 请求
/v1/user可能被误判为访问模块v1下的UserController,但该模块根本不存在,结果 404 - 若你后续真建了
modules/v1/目录,框架会优先加载模块而非走你写的路由规则,导致行为不一致 -
authenticator、rateLimiter等行为无法按版本差异化配置
正确做法是:每个版本对应一个显式声明的模块,ID 不叫 v1,改用 apiV1;路由前缀仍保留 v1/,但靠 UrlRule 映射到对应模块内部控制器。
模块 ID 和路由前缀必须错开
模块 ID 是代码识别符,路由前缀是 URL 路径的一部分,二者语义不能重叠。否则 Yii 2 的模块自动加载机制会抢在路由解析前介入。
- ❌ 错误:
'v1' => ['class' => 'api\modules\v1\Module']+'v1/<controller:>' => 'v1/<controller>'</controller></controller:> - ✅ 正确:
'apiV1' => ['class' => 'api\modules\apiV1\Module']+'v1/<controller:>' => 'api-v1/<controller>'</controller></controller:> - Yii 3 更推荐用
pattern+route显式解耦:['pattern' => 'v2/<controller:>', 'route' => 'api-v2/<controller>']</controller></controller:> - 模块内
controllerNamespace必须在Module.php中显式设置,不能依赖父级配置
共用模型怎么安全复用
模型层变更最容易引发跨版本故障。比如 v2 新增字段校验,结果 v1 接口因继承同一基类而意外失败。
- 禁止让
apiV1和apiV2直接共用同一个User类 - 定义接口契约,如
ApiUserContract,v1 和 v2 各自实现,各自覆盖rules()、scenarios() - 数据库迁移必须严格按版本隔离:v1 的迁移放
modules/apiV1/migrations/,v2 放modules/apiV2/migrations/,避免yii migrate时混入不该执行的变更 - 如果真要共享表结构,用视图或查询封装,别共享 ActiveRecord 类本身
中间件和行为怎么按版本生效
Auth、日志、参数校验这些逻辑,不能写在全局 bootstrap 或 common 层,否则 v1 和 v2 会被强绑定。
- 在模块的
init()方法中注册专属行为:$this->attachBehavior('auth', ['class' => JwtAuth::class]) - 中间件(如 Yii 3 的
MiddlewareInterface)需在路由解析后判断路径前缀:if (str_starts_with($request->getPathInfo(), '/v2/')) { ... } - 参数校验别堆在 action 里,统一用
ActionFilter,通过$action->id匹配预设规则数组,缺字段直接抛BadRequestHttpException -
BaseRestController中必须关掉session和autoLogin,但保留user组件初始化——token 验证依赖它,关掉就全挂
最常被忽略的是迁移文件的存放位置和模块命名空间的显式声明,这两处出错,轻则 404,重则 v1/v2 行为互相污染,查起来极难定位。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











