yii 的 urlmanager 支持伪静态路由映射、多端参数透传、跨域智能跳转及敏感参数隐藏。通过 rules 配置可实现内部转发、来源标识注入、hostinfo 动态适配,以及自定义 urlrule 加密处理。

Yii 的 UrlManager 不只是生成 URL 的工具,它还能实现灵活的路由跳转、参数透传、协议/域名自动适配,甚至在不改控制器逻辑的前提下完成页面重定向或 A/B 测试分流。关键在于理解规则匹配顺序、参数绑定机制和 request context 的联动方式。
用 rules 实现“伪静态跳转”而非硬重定向
很多人误以为要跳转就得写 header("Location: ...") 或返回 Response::redirect(),其实 UrlManager 可以在路由解析阶段就“悄悄换路”。只要配置一条带 pattern 和 route 的规则,并启用 suffix 或自定义 path,就能让访问 /old-product/123 自动映射到 product/view,且浏览器地址栏不变(即内部转发)。
- 确保
'enablePrettyUrl' => true和'showScriptName' => false已启用 - 在
urlManager->rules中添加:'old-product/<id:>' => 'product/view'</id:>
注意:这里没有redirect,是直接路由映射 - 控制器中仍用
$this->request->get('id')获取参数,无需额外解析
动态 route + params 绑定,实现多端页面复用
同一套 action 可服务 PC、H5、小程序等不同入口,只需在 URL 规则里注入来源标识,再通过 params 透传给 controller。Yii 会自动把规则中声明的命名参数(如 <source></source>)合并进 $_GET,且优先级高于 query string。
- 配置规则:
'app/<source:>/item/<id:>' => 'item/detail'</id:></source:> - 在
ItemController::actionDetail()中可直接:$source = \Yii::$app->request->get('source', 'pc');$id = \Yii::$app->request->get('id'); - 生成链接时用
Url::to(['item/detail', 'source' => 'h5', 'id' => 456]),UrlManager 会自动匹配最短合法规则并渲染为/app/h5/item/456
利用 hostInfo 和 baseUrl 做跨域/多环境智能跳转
当项目需支持 https://admin.example.com 跳转到 https://user.example.com/profile,又不想写死域名,可通过 UrlManager 的 hostInfo 动态计算。配合 Url::toRoute() 的数组语法,能自适应当前请求上下文。
- 在配置中设置:
'hostInfo' => \Yii::$app->request->getHostInfo()
(或更稳妥地用$_SERVER['HTTP_HOST']判断环境) - 跳转代码示例:
\Yii::$app->response->redirect(\yii\helpers\Url::toRoute(['//user/profile', 'id' => 789], true));
第二个参数true表示强制返回绝对 URL - 若需跳转到固定子域(如 always to
user.),可在 UrlManager 配置中加'hostInfo' => 'https://user.example.com',但建议封装成组件方法避免硬编码
隐藏参数但保留 SEO 友好路径的 trick
有些参数不适合暴露在 URL(如加密 token、临时 session id),又希望保持路径简洁,可用 UrlRule 子类 + createUrl()/parseRequest() 拦截处理。
- 新建类
SecureUrlRule继承\yii\web\UrlRule - 重写
parseRequest():从 path 提取 base64 编码段,解密后塞进$params并返回[route, $params] - 重写
createUrl():把敏感参数加密后拼入 path,如/post/SGVsbG8=→ 解出['post/view', 'title' => 'Hello'] - 注册规则时指定:
['class' => 'app\components\SecureUrlRule', 'pattern' => 'post/<token:>', 'route' => 'post/view']</token:>











