▪ 环境

基于《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 能根据右边的规则匹配出左边的数据

'/' => '//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/' => 'admin//index',

'admin//' => 'admin//',

'' => 'index/index/index',

'index' => 'index/index',

'' => 'index//index',

'/' => 'index//',

▪ 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',

'' => 'index//index',

'/' => 'index//',

]

编辑 '/frontend/modules/admin/Config.php',添加 rules 代码:

// URL

$configs['components']['urlManager'] = array();

$configs['components']['urlManager']['rules'] = [

'admin' => 'kernel/index/index',

'admin/' => 'kernel//index',

'admin//' => 'kernel//',

]

删除 /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,'getUrlManager()->addRules(array($k=>$rule));

foreach( $urlManagerRules AS $k=>$rule ) if( strpos($k,' 0 ) $application->getUrlManager()->addRules(array($k=>$rule));

foreach( $urlManagerRules AS $k=>$rule ) if( strpos($k,'getUrlManager()->addRules(array($k=>$rule));

}

}

> 在上面整合`ruels` 的代码中`rules` 项排在最后注:上面的代码中 越通用的 rules 项排在最后 的算法并没有真正实现,但是基本够用,以后有时间继续完善

将新的引导文件加入到 应用主体 的配置,编辑 /frontend/config/main.php,添加如下代码:$configs['bootstrap'] = array('frontend\modules\Bootstrap', 'log');

至此 URL 子模块伪独立配置高级写法 完成。

php yii2模块,Yii2 之 frontend 子模块实践之四:路由美化相关推荐

  1. php yii2模块,模块(Modules)

    模块 模块是独立的软件单元,由模型, 视图, 控制器和其他支持组件组成, 终端用户可以访问在应用主体中已安装的模块的控制器, 模块被当成小应用主体来看待,和应用主体不同的是, 模块不能单独部署,必须属 ...

  2. linux netfilter路由表,Linux netfilter 学习笔记 之十四 netfilter模块会修改数据包关联的路由缓存吗...

    起因: 最近在完成网关的一个相关功能时,对于网关本身通过socket发送的数据包,没有从正确的wan接口发送出去,但是在udp_sendmsg 函数里打印出来的 信息显示路由查找是正确的,但是当数据包 ...

  3. 四.卡尔曼滤波器(EKF)开发实践之四: ROS系统位姿估计包robot_pose_ekf详解

    本系列文章主要介绍如何在工程实践中使用卡尔曼滤波器,分七个小节介绍: 一.卡尔曼滤波器开发实践之一: 五大公式 二.卡尔曼滤波器开发实践之二:  一个简单的位置估计卡尔曼滤波器 三.卡尔曼滤波器(EK ...

  4. 大学计算机网络配置实验报告,北京理工大学-计算机网络实践-IP路由配置与路由协议分析实验报告.docx...

    北京理工大学-计算机网络实践-IP路由配置与路由协议分析实验报告.docx (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 LAB2 ...

  5. Arco Pro最佳实践,路由与菜单

    Arco Pro最佳实践,路由与菜单 1.路由 2.菜单 3.测试 1.路由 路由通常都和菜单绑定在一起,为了减少维护的量,Arco直接通过路由表生成了菜单. 首先,需要先了解一下路由表的配置 现在我 ...

  6. Android AR开发实践之四:基于Sceneform的ARcore开发实例

    Android AR开发实践之四:基于Sceneform的ARcore开发实例 一.设备配置 1.配置虚拟设备 2.配置真机 二.开发环境配置 1.首先添加sceneform的gradle插件到工程配 ...

  7. 怎样导入python colorama模块_使用git子模块导入python项目

    (我意识到在StackOverflow上有很多与python相关的导入相关的问题:我也怀疑我这样做是完全错误的:但是不管怎样,这里还是要说-) 我有一个python项目(mysubmod)组织如下:/ ...

  8. android+jacoco多模块项目中统计子模块代码覆盖率

    上一次做了单项目的代码覆盖率统计,但是在实际的项目中,都是已模块开发为主. 研究了一下怎么去统计子模块中的代码覆盖率. 整体思路: 1:既然是多模块的代码覆盖率统计,所以子模块必须也要是用jacoco ...

  9. yii2 / Console - yii2开发控制台应用时的还我漂漂拳

    之所以放到此专栏主要是该文章对我们学习yii2-queue有很大帮助. 我们经常使用yii2开发命令行应用,也会遇到比如让用户在命令行输入信息.选择等操作,今天为大家介绍的这个yii2的Console ...

最新文章

  1. Java学到什么水平能够出去找工作!
  2. 我常去的编程技术网站[最近更新:2010.09.29]
  3. python链表翻转_Python数据结构之旋转链表
  4. GO恶意样本实例分析
  5. 【蓝桥杯】题目 1429: 兰顿蚂蚁
  6. 4.GitLab 邮件配置
  7. 51单片机驱动WS2811彩灯源程序方案
  8. 爬虫实战之抓取猫眼电影排行TOP100(使用正则表达式提取数据)
  9. java实现即时通讯软件
  10. 高通量基因组测序中,什么是测序深度和覆盖度?
  11. pdf照片显示正常打印时被翻转_2020年二级建造师打印须知
  12. Linux中国 QQ 交流群 大全
  13. 微信公众平台编辑器可以剪裁和替换正文图片了
  14. 保险业的5项CX预测
  15. 【Qt5】创建文件夹
  16. python协程处理多个文件_python:多任务(线程、进程、协程)
  17. vue-router 报错Error: Avoided redundant navigation to current location: “/index/user“解决方式
  18. zeromq v.s. erlang
  19. 补:PE文件遍历导出表——有人为你哭,说明你还是个东西
  20. typeScript基础(1)_原始数据类型学习

热门文章

  1. Part 2 —— 迁移到 Go Modules
  2. prettier 指“北”
  3. MySql实现sequence功能的代码
  4. QT编译错误:invalid application of 'sizeof' to incomplete type 'Qt3DRender::QPickEvent'
  5. java中的final关键字(2013-10-11-163 写的日志迁移
  6. 一次比较麻烦的性能问题诊断及解决
  7. 第13条:合理利用try/expect/else/finally结构中的每个代码块
  8. JavaScript的DOM编程--01--js代码的写入位置
  9. pdf怎么转换成word文字版
  10. 本地邮件系统的安装及配置