上一节我们讲述了如何自定义后台的模版主题,小伙伴们纷纷采取+1的方式说我这是忽悠。
我:我这自定义了gii的模版,后台列表页、详情页以及表单页不就可以随便定制了么,主题的风格不也就切换了吗?
你:你这歪曲事实,这不是我想要的主题。我想要的是比如过个节,我要给后台的某些页面换一个节日主题,过了这个节或者再过下个节可以切换主题风格。
我:你这胡搅蛮缠,你这明明是前端的需求非要生拉硬拽提在后台的需求上。
你:是你说的,学习,跪在灵活变通。
我:……
桑心的分割线,你们这是在折磨我 ———————————————————————————–
我先出个妙招,过节嘛,换主题是吧,easy啊。你把页面拷贝一份,改改名字来个xxx.bak1,等再过一个节,再备份一个xxx.bak2,再升级优化页面再来个xxx.bak3,反反复复我保证你找不到哪个是哪个,哈哈哈……
玩笑归玩笑,这里首先先感谢有一群爱学的你们提的好建议,其次再次感谢付费用户的支持,有你们的支持,才让我如此的坚持。来,我们继续看看这节要讲述的主题:“主题”。
关于要定制主题的原因前面我们开玩笑已经提过了,而且大多数场景下也确确实实是需要的。比如,我们要求pc和h5共用一套程序,但是h5采用另一套主题,该怎么做才是比较好的方案呢?
我们先来看下平时用render是如何渲染视图文件的。
通过层层源码追踪,我们在 vendor\yiisoft\yii2\base\View 的 renderFile 方法中找到这么一段代码1
2
3
4
5
6
7
8
9public function renderFile($viewFile, $params = [], $context = null)
{
$viewFile = Yii::getAlias($viewFile);
if ($this->theme !== null) {
$viewFile = $this->theme->applyTo($viewFile);
}
// ......
}
此处只需要看懂这里所列的 if 判断语句就行了,其他的先忽略掉。也就是说,在底层渲染视图文件的时候,有对主题进行过判断,动动手指头也能明白,如果设置了主题,将会渲染我们自己设置的主题模版。这里的 $this->theme 其实是 yii\base\Theme类(vendor\yiisoft\yii2\base\Theme类)的实例。通常我们根据Theme 设置主题,主要有静态设置和动态设置两种。先来看静态设置
所谓的静态设置,就是在配置文件中配置好,该渲染谁就渲染谁。
打开配置文件,backend\config\main.php文件,在components中添加如下配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14'components' => [
// ...
'view' => [
'theme' => [
// 'basePath' => '@app/themes/spring',
// 'baseUrl' => '@web/themes/spring',
'pathMap' => [
'@app/views' => [
'@app/themes/spring',
]
],
],
],
],
下面简单说明一下这几个配置项的意义:
basePath和baseUrl分别是对资源的目录和资源的url进行配置
pathMap从名字上不难分析出其是路径的一个映射,说白了就是对@app/view路径替换为@app/themes/spring
来做几个小例子加以说明:
首先在应用的根目录(@app是指应用所在的顶级目录)backend下创建目录 themes/spring
我们以上一章节新建的测试表test为例,在gii生成完模版后,我们访问 index.php?r=test 可以看到列表页展示的是gridview数据列表。在我们已经自定义theme为spring的情况下,我们在spring目录下新建test/index.php,随便写点什么,如:
This is spring custom test/index views.
此时刷新下 index.php?r=test,你会意外的发现页面的显示的内容竟然是我们自定义的spring/test/index.php文件的内容 !也就是说我们成功的通过pathMap把@app/views映射到了@app/themes/spring/下面了!当然,你也可以定义多个映射关系,比如说又过圣诞节了1
2
3
4
5
6'pathMap' => [
'@app/views' => [
'@app/themes/christmas',
'@app/themes/spring',
]
],
只需要把chrismas主题配置到属组的第一项即可,因为前面的优先级比后面高,如果前面的模版找不到才会用下面的spring主题模版。spring我们来年可以继续使用,如果你的项目到时候还存在的话。
不知道你看懂了没有呢?有任何问题可以下面留言哦!哦不,我们这节好像还没说完,动态渲染主题的还没说,差点错过了什么!
以前面的问题为例,我们现在一个应用,通过不同的客户端,如何动态渲染不同的模版主题?
为了演示说明问题,我们仍然以访问 /index.php?r=test 为例,只不过如果 $_GET有参数switch且值为真就显示spring主题,值为假就显示christmas主题。来看下怎么破!
首先我们先把配置文件中的主题配置屏蔽掉,记得先屏蔽掉。
为了一箭三雕:
1、更好的给部分人开辟向前的道路,避免一些错误的走向
2、巩固学习的知识,灵活的使用行为
3、为了后面我们要说的事件,预热
我们这里配置行为来进行问题说明:
首先打开 backend\config\main.php 在components同级,增加如下的行为配置。记得是同级,不要放错了位置1
2
3'as theme' => [
'class' => 'backend\components\ThemeControl',
],
然后,我们在 backend\components 目录下新建 ThemeControl.php 文件,增加如下代码段1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<?php
namespace backend\components;
use Yii;
use yii\base\Object;
class ThemeControl extends \yii\base\ActionFilter
{
public function init ()
{
$switch = intval(Yii::$app->request->get('switch'));
$theme = $switch ? 'spring' : 'christmas';
Yii::$app->view->theme = Yii::createObject([
'class' => 'yii\base\Theme',
'pathMap' => [
'@app/views' => [
"@app/themes/{$theme}",
]
],
]);
}
}
代码的作用就是动态根据$_GET变量switch进行切换主题。
对其中的两点我们做一个解释:
1、我们在开篇了解到 在yii\base\View 类中可以通过 $this->theme 可以访问 yii\base\Theme 类的实例以及我们刚刚通过配置 view 来配置不同的 theme。这也就不难明白,theme可以通过 Yii::$app->view->theme 进行配置
2、我们在配置一文中讲到,yii2的配置,比如刚刚配置的view一定是针对对象进行的配置,配置这个对象最终的实例化过程就是通过 yii\base\Object 进行创建的。也就不难理解我们这里用 Yii::createObject 创建主题对象的写法了!
光记得说忘记测试了,大家自己个通过访问 /index.php?r=test&switch=1 和 /index.php?r=test&switch=0 试试