Yii2 之 frontend 子模块实践之四:路由美化 [ 2.0 版本 ]
▪ 环境
基于《Yii2 之 frontend 子模块实践之一:添加前后台子模块》。
基于《Yii2 之 frontend 子模块实践之二:构建子模块的独立配置》。
基于《Yii2 之 frontend 子模块实践之三:布局和语言配置》。
▪ 前言
到目前为止,我们都是通过以下的 URL 访问 子模块:
# 前台 index 子模块
http://frontend.domain.com/index.php?r=index/site/index
http://frontend.domain.com/index.php?r=index/about/index
http://frontend.domain.com/index.php?r=index/product/view&id=1
...
# 后台 admin 子模块
http://frontend.domain.com/index.php?r=admin/site/index
http://frontend.domain.com/index.php?r=admin/admin/login
...
很明显,这些 URL 格式对于一些稍微有 SEO 要求的项目就不行了。在下面的内容中我们将介绍利用 Yii2 内置的重写功能来不断美化 URL。
▪ 子模块和 URL 美化联动问题
对于一个项目,也许你可能只想美化 前台子模块 部分的 URL 格式,而对于 后台子模块 没有美化的要求,用原始的 URL 即可。
但是很不幸,Yii2 的 URL 美化是 应用主体 级别的。也就是说一旦你启用了 URL 美化,那么 应用主体 下的全部 子模块 都将启用 URL 美化。没有办法单独为一个 子模块 启用 URL 美化。
这里不探索具体为什么会这样,不过大概原因就是:URL 美化是在应用主体构建前期的 bootstrap 阶段就会完成,而子模块都是应用主体后期才构建的,所以无法为子模块单独配置 URL 美化。
▪ URL 美化之简易版
要想启用 URL 美化,只需要编辑 /frontend/config/main.php
,添加如下代码即可:
// URL
$configs['components']['urlManager'] = array();
$configs['components']['urlManager']['rules'] = array();
$configs['components']['urlManager']['suffix'] = '.html';
$configs['components']['urlManager']['showScriptName'] = false;
$configs['components']['urlManager']['enablePrettyUrl'] = true;
美化之后,项目的一些 URL 变化如下:
# 前台 index 子模块
http://frontend.domain.com/index/site/index.html
http://frontend.domain.com/index/index/index.html
http://frontend.domain.com/index/product/view/id/1.html
...
# 后台 admin 子模块
http://frontend.domain.com/admin/site/index.html
http://frontend.domain.com/admin/admin/login.html
...
▪ URL 美化之高级版
URL 高级美化,其实就是利用 urlManager
的 rules
对 URL 再做进一步的美化;rules
可以为单独的一条 URL 做定制美化,也可以为有相同规则的 URL 做批量定制美化。
1. 去除控制器中 Action 的 index
编辑 /frontend/config/main.php
,在 $configs['components']['urlManager']['rules']
中添加如下代码:
# 在通过 URL 访问时,Yii2 能将 URL 按照左边的规则匹配出右边的数据并进行路由
# 而在利用 urlManager 构建输出 URL 时,Yii2 能根据右边的规则匹配出左边的数据
'<module>/<controller>' => '<module>/<controller>/index',
对于访问控制器的 URL,如果没有指明控制器的 Action,那么 Yii2 默认就是使用 actionIndex
。此处我们将这条规则强制写到规则 rules
里面,看上去也许可能没什么作用,但是当你使用 Url::toRoute('index/site/index')
的生成 URL 时候其作用就体现了出来了:
# 没有使用规则那么会生成以下 URL
/index/site/index.html
# 使用了规则的则会生成以下 URL
/index/site.html
最后我们来看下使用上面的规则以后,项目的一些 URL 变化如下:
# 前台 index 子模块
http://frontend.domain.com/index/site.html // Change
http://frontend.domain.com/index/index.html // Change
http://frontend.domain.com/index/product/view/id/1.html
...
# 后台 admin 子模块
http://frontend.domain.com/admin/site.html // Change
http://frontend.domain.com/admin/admin/login.html
...
▪ URL 美化之子模块伪独立配置
之前我们说过 子模块 的是无法独立配置 URL 美化的,的确没错。但是接下来我们将利用 rules
规则的优先级来模拟一个 子模块伪独立配置,虽然不能完全独立,但是也基本满足日常需求。
在上面的案例中,我们发现 子模块 的名称都是存在于 URL 中的:
http://frontend.domain.com/index/... // 前台 index 子模块
http://frontend.domain.com/admin/... // 后台 admin 子模块
我们的目标很简单,就是 前台子模块 的名称 index
不要存在于 URL 中,例如:
// 直接访问
// 前台 index 子模块
http://frontend.domain.com/site.html
http://frontend.domain.com/about.html
// 访问 后台 admin 子模块
http://frontend.domain.com/admin/site.html
http://frontend.domain.com/admin/about.html
这在我们日常的网站中非常常见,没有见过哪个网站的前台是
index
开头,所以如果不能实现上面的 URL 规则,那么 《Yii2 之 frontend 子模块》 这个系列教程也就基本没有意义了。
注意:该方案仅仅 前台子模块 的 可以省略模块名称(
index
),其他的 子模块 名称还是必须要存在于 URL 中。
基本思路:
urlManager
的 rules
规则匹配是从上到下,一旦匹配到那么即刻终止。利用该规律,我们可以先把所有的 其他子模块 通用规则写全:这样访问 其他子模块 的 URL 将优先被rules
匹配,直接路由进入对应的子模块。
然后我们将 前台 index 子模块 的规则写入到 rules
的最后,同时省略模块名称 index
,这样就实现上面的需求。
代码实现:
编辑 /frontend/config/main.php
,在 $configs['components']['urlManager']['rules']
中添加如下代码:
'admin' => 'admin/index/index',
'admin/<controller>' => 'admin/<controller>/index',
'admin/<controller>/<action>' => 'admin/<controller>/<action>',
'' => 'index/index/index',
'index' => 'index/index',
'<controller>' => 'index/<controller>/index',
'<controller>/<action>' => 'index/<controller>/<action>',
▪ URL 子模块伪独立配置高级写法
到此为止,我们已经完成了 子模块伪独立配置,系统也能非常成功的运行了。
也许你有洁癖,你发现将全部子模块的 rules
写在 应用主体 的配置文件中很是不爽。
在之前的系列文章 《Yii2 之 frontend 子模块实践之二:构建子模块的独立配置》 中我们已经为每个子模块分配了独立的配置文件,那么我们能不能将每个子模块的 rules
写到各自的独立配置文件中呢?这些无论是结构上还是逻辑上都将更加清晰。
不要尝试把 URL 美化的启动配置写到每个子模块的独立文件中,这个其实是无效的,因为 Yii2 在还没构建子模块实例时就已经加载了URL路由的配置并实例化路由对象
A. 分离 rules
编辑 '/frontend/modules/index/Config.php',添加
rules
代码:// URL $configs['components']['urlManager'] = array(); $configs['components']['urlManager']['rules'] = [ '' => 'index/index/index', 'index' => 'index/index', '<controller>' => 'index/<controller>/index', '<controller>/<action>' => 'index/<controller>/<action>', ]
编辑 '/frontend/modules/admin/Config.php',添加
rules
代码:// URL $configs['components']['urlManager'] = array(); $configs['components']['urlManager']['rules'] = [ 'admin' => 'kernel/index/index', 'admin/<controller>' => 'kernel/<controller>/index', 'admin/<controller>/<action>' => 'kernel/<controller>/<action>', ]
删除
/frontend/config/main.php
中的$configs['components']['urlManager']['rules'] ...
B. 在应用主体的 bootstrap 阶段整合 rules
配置
由于 Yii2 的在构建 子模块 之前就已经构建好了路由对象,所以想要 子模块配置文件 中的 rules
规则应用于 Yii2 的路由对象,那么必须在 bootstrap 阶段就要整合 rules
。
- 新建引导文件
/frontend/modules/Bootstrap.php
,引导文件内容如下:<?php namespace frontend\modules;
use yii\base\BootstrapInterface;
/**
前端引导类
/
class Bootstrap implements BootstrapInterface
{
/*@param \yii\base\Application $application
*/
public function bootstrap( $application )
{
// 初始化
$urlManagerRules = array();// 获取模块集
$modules = $application->getModules();// 配置 UrlManager 的规则集
// 没有使用正则匹配的规则优先级高
// 通用性高的正则匹配的规则优先级越低
foreach( $modules as $key => $module ){// 过滤系统内置模块 if( is_array($module) == false ) continue; if( strpos($module['class'],'frontend\modules') !== 0 ) continue; // 获取自定义模块的配置 $config = __DIR__ .'/'. $key . '/Config.php'; if( is_file($config) == false ) continue; $config = require($config); // 配置 UrlManager 组件的规则 $rules = $config['components']['urlManager']['rules']; if( empty($rules) ) continue; $urlManagerRules = array_merge($urlManagerRules, $rules);
}
foreach( $urlManagerRules AS $k=>$rule ) if( strpos($k,'<') === false ) $application->getUrlManager()->addRules(array($k=>$rule));
foreach( $urlManagerRules AS $k=>$rule ) if( strpos($k,'<') !== false && strpos($k,'<') > 0 ) $application->getUrlManager()->addRules(array($k=>$rule));
foreach( $urlManagerRules AS $k=>$rule ) if( strpos($k,'<') !== false && strpos($k,'<') == 0 ) $application->getUrlManager()->addRules(array($k=>$rule));
}
}> 在上面整合 `ruels` 的代码中,我并没有将 admin 和 index 两个子模块的名称写死。而是换了另外一种思路:越通用的 `rules` 项排在最后。这样既能实现之前的URL美化规则,同时也能大大提高程序的通用性。就算以后新加子模块此处的代码也无需修改。
注:上面的代码中 越通用的
rules
项排在最后 的算法并没有真正实现,但是基本够用,以后有时间继续完善
- 将新的引导文件加入到 应用主体 的配置,编辑
/frontend/config/main.php
,添加如下代码:$configs['bootstrap'] = array('frontend\modules\Bootstrap', 'log');
至此 URL 子模块伪独立配置高级写法 完成。
mycjk31
最后登录:23小时前
在线时长:10小时41分
- 粉丝7
- 金钱150
- 威望130
- 积分1550
共 1 条评论
不错的yii2路由设置简易教程,支持