yii 3 路由机制彻底重构:移除模块自动发现和旧式 urlmanager,改用 psr-15 兼容的 router 组件,采用对象化声明、显式处理器绑定、命名路由 url 生成及模块与路由解耦。

Yii 1.1 升级到 Yii 3 后,路由机制发生了根本性变化:Yii 3 彻底移除了“模块自动发现”和基于 CWebApplication 的旧式路由解析逻辑,转而采用 PSR-15 兼容的独立路由器组件(yiisoft/router),路由定义方式、匹配顺序、参数绑定和 URL 生成逻辑全部重构。直接沿用 Yii 1.1 的 rules 数组配置会完全失效。
路由配置位置从 urlManager 移到了 router 组件
Yii 1.1 中路由写在 components['urlManager']['rules'];
Yii 3 中不再有 urlManager,而是通过 Router 实例注册路由规则,通常在 config/web.php 或 DI 容器配置中完成:
use Yiisoft\Router\Group;
use Yiisoft\Router\Route;
return [
'router' => [
'__class' => \Yiisoft\Router\Router::class,
'__construct()' => [
'routes' => [
// v1 API 路由组
Group::create('/api/v1')
->addRoutes([
Route::get('/users', 'api-v1/user:list'),
Route::get('/users/{id:\d+}', 'api-v1/user:view'),
]),
// v2 API 路由组
Group::create('/api/v2')
->addRoutes([
Route::get('/users', 'api-v2/user:list'),
Route::post('/users', 'api-v2/user:create'),
]),
// 前台页面
Route::get('/', 'site/home'),
Route::get('/contact', 'site/contact'),
],
],
],
];
✅ 关键点:路由是「对象化声明」,不是字符串映射;路径前缀(如
/api/v1)直接参与匹配,无需额外解析或enableStrictParsing控制。
路由匹配逻辑更严格、无隐式 fallback
Yii 1.1 的 'user/<id:>' => 'user/view'</id:> 是模糊重写,框架会尝试填充参数并跳转控制器;
Yii 3 的路由必须显式绑定处理器(handler),且不支持泛匹配兜底(如 <controller>/</controller>)。没有匹配的路由,默认返回 404 —— 不再自动 fallback 到 SiteController::actionIndex()。
- ❌ 不再支持:
'<controller:>/<id:>' => '<controller>/view', '<controller:>/' => '<controller>/index',</controller></controller:></controller></id:></controller:>
- ✅ 正确做法:按业务边界逐条定义,或用
Group+RouteCollector批量注册:Group::create('/admin') ->addRoutes( (new RouteCollector()) ->addGet('{controller:\w+}/{id:\d+}', '{controller}/view') ->addGet('{controller:\w+}', '{controller}/index') ),
但注意:这种动态模式需配合自定义 HandlerResolver,不推荐用于生产环境——易引发歧义和调试困难。
URL 生成方式彻底改变:从 createUrl() 到 UrlGenerator
Yii 1.1 中 Yii::app()->createUrl('post/view', ['id' => 123]) 依赖逆向规则匹配;
Yii 3 中使用 UrlGeneratorInterface::generate(),必须指定命名路由名(name),否则无法生成:
// 定义时带 name
Route::get('/posts/{id:\d+}', 'post/view')->name('post.view'),
// 生成时引用 name
$url = $urlGenerator->generate('post.view', ['id' => 123]); // → /posts/123
- 没有
name的路由无法被generate()识别; - 参数缺失会抛出
InvalidArgumentException,不会静默丢弃; - 不再支持
['post/view', 'id' => 123]这类数组式调用。
模块与路由解耦,不再靠目录结构自动加载
Yii 1.1 中 modules/v1/ + urlManager 规则可联动;
Yii 3 中模块(Module)不参与路由分发,只是组织代码的逻辑单元。路由 handler 可以指向任意可调用对象(闭包、服务 ID、控制器方法),与模块目录无关:
// handler 可以是:
'api-v1/user:list', // service ID(由 DI 容器解析)
[UserListAction::class, 'run'], // 类+方法
fn() => new Response('OK') // 闭包
若仍想按版本隔离,推荐:
- 将
apiV1和apiV2设为独立服务(如api-v1/user:listvsapi-v2/user:list); - 在 handler 内部做权限、字段、响应格式区分;
- 共用模型通过接口契约(如
UserContract)注入,避免硬依赖。
不复杂但容易忽略










