在模板中输出变量的方法很简单,例如
~~~
{$name}
~~~
模板编译后的结果就是:
~~~
<?php echo htmlentities($name);?>
~~~
注意模板标签的`{`和`$`之间不能有任何的空格,否则标签无效。所以,下面的标签
~~~
{ $name}
~~~
将不会正常输出name变量,而是直接保持不变输出:
模板标签的变量输出根据变量类型有所区别,刚才我们输出的是字符串变量,如果是数组变量
~~~
$data['name'] = 'ThinkPHP';
$data['email'] = 'thinkphp@qq.com';
~~~
那么,在模板中我们可以用下面的方式输出:
~~~
Name:{$data.name}
Email:{$data.email}
~~~
或者用下面的方式也是有效:
~~~
Name:{$data['name']}
Email:{$data['email']}
~~~
>[info] 当我们要输出多维数组的时候,往往要采用后面一种方式。
如果`data`变量是一个对象(并且包含有`name`和`email`两个属性),那么可以用下面的方式输出:
~~~
Name:{$data->name}
Email:{$data->email}
~~~
也可以直接调用对象的常量或者方法
~~~
常量:{$data::CONST_NAME}
方法:{$data->fun()}
~~~
## 使用默认值
我们可以给变量输出提供默认值,例如:
~~~
{$user.nickname|default="这家伙很懒,什么也没留下"}
~~~
对系统变量依然可以支持默认值输出,例如:
~~~
{$Think.get.name|default="名称为空"}
~~~
默认值和函数可以同时使用,例如:
~~~
{$Think.get.name|getName|default="名称为空"}
~~~
## 系统变量输出
普通的模板变量需要首先赋值后才能在模板中输出,但是系统变量则不需要,可以直接在模板中输出,系统变量的输出通常以`{$Think.`(大小写一致) 打头,例如:
~~~
{$Think.server.script_name} // 输出$_SERVER['SCRIPT_NAME']变量
{$Think.session.user_id} // 输出$_SESSION['user_id']变量
{$Think.get.page} // 输出$_GET['page']变量
{$Think.cookie.name} // 输出$_COOKIE['name']变量
~~~
支持输出`$_SERVER`、`$_ENV`、`$_POST`、`$_GET`、`$_REQUEST`、`$_SESSION`和`$_COOKIE`变量。
## 常量输出
还可以输出常量
~~~
{$Think.const.PHP_VERSION}
~~~
或者直接使用
~~~
{$Think.PHP_VERSION}
~~~
## 配置输出
输出配置参数使用:
~~~
{$Think.config.default_module}
{$Think.config.default_controller}
~~~
## 使用函数
需要对模板输出使用函数进行过滤或其它处理的时候,可以使用:
~~~
{$data.name|md5}
~~~
可以使用空格,例如下面的写法是一样的:
~~~
{$data.name | md5}
~~~
编译后的结果是:
~~~
<?php echo htmlentities(md5($data['name'])); ?>
~~~
其中`htmlentities`方法是系统默认添加的(无需手动指定。
> 为了避免出现XSS安全问题,默认的变量输出都会使用`htmlentities`方法进行转义输出。
你还可以设置默认的过滤方法,在配置文件`template.php`中设置
~~~
'default_filter' => 'htmlspecialchars'
~~~
就会默认使用`htmlspecialchars`方法过滤输出。
如果你不需要转义(例如你需要输出html表格等内容),可以使用:
~~~
{$data.name|raw}
~~~
编译后的结果是:
~~~
<?php echo $data['name']; ?>
~~~
系统内置了下面几个固定的过滤规则(不区分大小写)
| 过滤方法 | 描述 |
| --- | --- |
| date | 日期格式化(支持各种时间类型) |
| format | 字符串格式化 |
| upper | 转换为大写 |
| lower | 转换为小写 |
| first | 输出数组的第一个元素 |
| last | 输出数组的最后一个元素 |
| default | 默认值 |
| raw | 不使用(默认)转义 |
例如
~~~
{$data.create_time|date='Y-m-d H:i'}
{$data.number|format='%02d'}
~~~
如果函数有多个参数需要调用,可以使用
~~~
{$data.name|substr=0,3}
~~~
表示输出
~~~
<?php echo htmlentities(substr($data['name'],0,3)); ?>
~~~
还可以支持多个函数过滤,多个函数之间用“|”分割即可,例如:
~~~
{$name|md5|upper|substr=0,3}
~~~
编译后的结果是:
~~~
<?php echo htmlentities(substr(strtoupper(md5($name)),0,3)); ?>
~~~
函数会按照从左到右的顺序依次调用(系统默认的过滤规则会在最后调用)。
> 变量输出使用的函数可以支持内置的PHP函数或者用户自定义函数,甚至是静态方法。
如果你觉得这样写起来比较麻烦,也可以直接这样写:
~~~
{:substr(strtoupper(md5($name)),0,3)}
~~~
> 使用该方法输出的值不会使用默认的过滤方法进行转义。
## 运算符
我们可以对模板输出使用运算符,包括如下支持。
| 运算符 | 使用示例 |
| --- | --- |
| `+` | `{$a+$b}` |
| `-` | `{$a-$b}` |
| `*` | `{$a*$b}` |
| `/` | `{$a/$b}` |
| `%` | `{$a%$b}` |
| `++` | `{$a++}`或`{++$a}` |
| `--` | `{$a--}`或`{--$a}` |
| 综合运算 | `{$a+$b*10+$c}` |
在使用运算符的时候,不再支持前面提到的函数过滤用法,例如:
~~~
{$user.score+10} //正确的
{$user['score']+10} //正确的
{$user['score']*$user['level']} //正确的
{$user['score']|myFun*10} //错误的
{$user['score']+myFun($user['level'])} //正确的
~~~
### 三元运算
模板可以支持三元运算符,例如:
~~~
{$status? '正常' : '错误'}
{$info['status']? $info['msg'] : $info['error']}
{$info.status? $info.msg : $info.error }
~~~
还支持如下的写法:
~~~
{$name ?? '默认值'}
~~~
表示如果有设置`$name`则输出`$name`,否则输出`默认值`。
~~~
{$name?='默认值'}
~~~
表示$name为真时才输出默认值。
~~~
{$name ?: 'NO'}
~~~
表示如果$name为真则输出$name,否则输出NO。
~~~
{$a==$b ? 'yes' : 'no'}
~~~
前面的表达式为真输出yes,否则输出no, 条件可以是==、===、!=、!==、>=、<=
## 包含文件
在当前模版文件中包含其他的模版文件使用include标签,标签用法:
~~~
{include file='模版文件1,模版文件2,...' /}
~~~
### 使用模版文件
可以直接包含一个模版文件名(包含完整路径),例如:
~~~
{include file="../application/view/default/public/header.html" /}
~~~
### 传入参数
无论你使用什么方式包含外部模板,Include标签支持在包含文件的同时传入参数,例如,下面的例子我们在包含header模板的时候传入了`title`和`keywords`参数:
~~~
{include file="Public/header" title="$title" keywords="开源WEB开发框架" /}
~~~
就可以在包含的header.html文件里面使用title和keywords变量,如下:
~~~
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>[title]</title>
<meta name="keywords" content="[keywords]" />
</head>
~~~
上面title参数传入的是个变量`$title`,模板内的`[title]`最终会替换成`$title`的值,当然`$title`这个变量必须要存在。
# 循环标签
*****
## `FOREACH`标签
`foreach`标签的用法和PHP语法非常接近,用于循环输出数组或者对象的属性,用法如下:
~~~
$list = User::all();
$this->assign('list',$list);
~~~
模板文件中可以这样输出
~~~
{foreach $list as $key=>$vo }
{$vo.id}:{$vo.name}
{/foreach}
~~~
可以不通过模板变量赋值,支持使用函数或者方法获取数据循环输出:
~~~
{foreach :model('user')->all() as $key=>$vo }
{$vo.id}:{$vo.name}
{/foreach}
~~~
## `VOLIST`标签
`volist`标签通常用于查询数据集或者二维数组的结果输出。 在控制器中首先对模版赋值:
~~~
$list = User::all();
$this->assign('list',$list);
~~~
在模版定义如下,循环输出用户的编号和姓名:
~~~
{volist name="list" id="vo"}
{$vo.id}:{$vo.name}<br/>
{/volist}
~~~
`Volist`标签的`name`属性表示模板赋值的变量名称,因此不可随意在模板文件中改变。`id`表示当前的循环变量,可以随意指定,但确保不要和`name`属性冲突,例如:
~~~
{volist name="list" id="data"}
{$data.id}:{$data.name}<br/>
{/volist}
~~~
可以直接使用函数设定数据集,而不需要在控制器中给模板变量赋值传入数据集变量,如:
~~~
{volist name=":model('user')->all()" id="vo"}
{$vo.name}
{/volist}
~~~
支持输出查询结果中的部分数据,例如输出其中的第5~15条记录
~~~
{volist name="list" id="vo" offset="5" length='10'}
{$vo.name}
{/volist}
~~~
输出偶数记录
~~~
{volist name="list" id="vo" mod="2" }
{eq name="mod" value="1"}{$vo.name}{/eq}
{/volist}
~~~
`mod`属性还用于控制一定记录的换行,例如:
~~~
{volist name="list" id="vo" mod="5" }
{$vo.name}
{eq name="mod" value="4"}<br/>{/eq}
{/volist}
~~~
为空的时候输出提示:
~~~
{volist name="list" id="vo" empty="暂时没有数据" }
{$vo.id}|{$vo.name}
{/volist}
~~~
`empty`属性不支持直接传入html语法,但可以支持变量输出,例如:
~~~
$this->assign('empty','<span class="empty">没有数据</span>');
$this->assign('list',$list);
~~~
然后在模板中使用:
~~~
{volist name="list" id="vo" empty="$empty" }
{$vo.id}|{$vo.name}
{/volist}
~~~
输出循环变量:
~~~
{volist name="list" id="vo" key="k" }
{$k}.{$vo.name}
{/volist}
~~~
如果没有指定`key`属性的话,默认使用循环变量i,例如:
~~~
{volist name="list" id="vo" }
{$i}.{$vo.name}
{/volist}
~~~
如果要输出数组的索引,可以直接使用`key`变量,和循环变量不同的是,这个`key`是由数据本身决定,而不是循环控制的,例如:
~~~
{volist name="list" id="vo" }
{$key}.{$vo.name}
{/volist}
~~~
## `FOR`标签
用法:
~~~
{for start="开始值" end="结束值" comparison="" step="步进值" name="循环变量名" }
{/for}
~~~
开始值、结束值、步进值和循环变量都可以支持变量,开始值和结束值是必须,其他是可选。comparison 的默认值是lt,name的默认值是i,步进值的默认值是1,举例如下:
~~~
{for start="1" end="100"}
{$i}
{/for}
~~~
解析后的代码是
~~~
for ($i=1;$i<100;$i+=1){
echo $i;
}
~~~
# 比较标签
*****
比较标签用于简单的变量比较,复杂的判断条件可以用if标签替换,比较标签是一组标签的集合,基本上用法都一致,如下:
~~~
{比较标签 name="变量" value="值"}
内容
{/比较标签}
~~~
系统支持的比较标签以及所表示的含义分别是:
| 标签 | 含义 |
| --- | --- |
| eq或者 equal | 等于 |
| neq 或者notequal | 不等于 |
| gt | 大于 |
| egt | 大于等于 |
| lt | 小于 |
| elt | 小于等于 |
| heq | 恒等于 |
| nheq | 不恒等于 |
他们的用法基本是一致的,区别在于判断的条件不同,并且所有的比较标签都可以和else标签一起使用。
例如,要求name变量的值等于value就输出,可以使用:
~~~
{eq name="name" value="value"}value{/eq}
~~~
或者
~~~
{equal name="name" value="value"}value{/equal}
~~~
也可以支持和else标签混合使用:
~~~
{eq name="name" value="value"}
相等
{else/}
不相等
{/eq}
~~~
当 name变量的值大于5就输出
~~~
{gt name="name" value="5"}value{/gt}
~~~
当name变量的值不小于5就输出
~~~
{egt name="name" value="5"}value{/egt}
~~~
比较标签中的变量可以支持对象的属性或者数组,甚至可以是系统变量,例如: 当vo对象的属性(或者数组,或者自动判断)等于5就输出
~~~
{eq name="vo.name" value="5"}
{$vo.name}
{/eq}
~~~
当vo对象的属性等于5就输出
~~~
{eq name="vo:name" value="5"}
{$vo.name}
{/eq}
~~~
当$vo\['name'\]等于5就输出
~~~
{eq name="vo['name']" value="5"}
{$vo.name}
{/eq}
~~~
而且还可以支持对变量使用函数 当vo对象的属性值的字符串长度等于5就输出
~~~
{eq name="vo:name|strlen" value="5"}{$vo.name}{/eq}
~~~
变量名可以支持系统变量的方式,例如:
~~~
{eq name="Think.get.name" value="value"}相等{else/}不相等{/eq}
~~~
通常比较标签的值是一个字符串或者数字,如果需要使用变量,只需要在前面添加“$”标志: 当vo对象的属性等于$a就输出
~~~
{eq name="vo:name" value="$a"}{$vo.name}{/eq}
~~~
所有的比较标签可以统一使用compare标签(其实所有的比较标签都是compare标签的别名),例如: 当name变量的值等于5就输出
~~~
{compare name="name" value="5" type="eq"}value{/compare}
~~~
等效于
~~~
{eq name="name" value="5" }value{/eq}
~~~
其中type属性的值就是上面列出的比较标签名称
# 条件判断
*****
## SWITCH标签
**用法:**
~~~
{switch 变量 }
{case value1 }输出内容1{/case}
{case value2}输出内容2{/case}
{default /}默认情况
{/switch}
~~~
使用示例:
~~~
{switch User.level}
{case 1}value1{/case}
{case 2}value2{/case}
{default /}default
{/switch}
~~~
可以使用函数以及系统变量,例如:
~~~
{switch User.level|intval }
{case 1}admin{/case}
{default /}default
{/switch}
~~~
对于case属性可以支持多个条件的判断,使用”|”进行分割,例如:
~~~
{switch Think.get.type}
{case gif|png|jpg}图像格式{/case}
{default /}其他格式
{/switch}
~~~
表示如果`$_GET["type"]`是gif、png或者jpg的话,就判断为图像格式。
也可以对case的value属性使用变量,例如:
~~~
{switch $User.userId}
{case $adminId}admin{/case}
{case $memberId}member{/case}
{/switch}
~~~
> 使用变量方式的情况下,不再支持`|`分割的多个条件判断用法。
## IF标签
**用法:**
~~~
{if 表达式}value1
{elseif 表达式 /}value2
{else /}value3
{/if}
~~~
用法示例:
~~~
{if ( $name == 1) OR ( $name > 100) } value1
{elseif $name == 2 /}value2
{else /} value3
{/if}
~~~
可以使用php代码,例如:
~~~
{if strtoupper($user['name']) == 'THINKPHP' }ThinkPHP
{else /} other Framework
{/if}
~~~
判断条件可以支持点语法和对象语法,例如:
~~~
{if $user.name == 'ThinkPHP'}ThinkPHP
{else /} other Framework
{/if}
{if $user->name == 'ThinkPHP'}ThinkPHP
{else /} other Framework
{/if}
~~~
> 如果某些特殊的要求下面,IF标签仍然无法满足要求的话,可以使用原生php代码或者PHP标签来直接书写代码。
## 范围判断
范围判断标签包括`in`/`notin`/`between`/`notbetween`四个标签,都用于判断变量是否中某个范围。
### IN和NOTIN
用法: 假设我们中控制器中给id赋值为1:
~~~
$id = 1;
$this->assign('id',$id);
~~~
我们可以使用in标签来判断模板变量是否在某个范围内,例如:
~~~
{in name="id" value="1,2,3"}
id在范围内
{/in}
~~~
最后会输出:`id在范围内`。
如果判断不在某个范围内,可以使用notin标签:
~~~
{notin name="id" value="1,2,3"}
id不在范围内
{/notin}
~~~
最后会输出:`id不在范围内`。
可以把上面两个标签合并成为:
~~~
{in name="id" value="1,2,3"}
id在范围内
{else/}
id不在范围内
{/in}
~~~
name属性还可以支持直接判断系统变量,例如:
~~~
{in name="Think.get.id" value="1,2,3"}
$_GET['id'] 在范围内
{/in}
~~~
> 更多的系统变量用法可以参考[系统变量](https://www.kancloud.cn/manual/thinkphp5_1/125004)部分。
value属性也可以使用变量,例如:
~~~
{in name="id" value="$range"}
id在范围内
{/in}
~~~
$range变量可以是数组,也可以是以逗号分隔的字符串。
value属性还可以使用系统变量,例如:
~~~
{in name="id" value="$Think.post.ids"}
id在范围内
{/in}
~~~
### BETWEEN 和 NOTBETWEEN
可以使用`between`标签来判断变量是否在某个区间范围内,可以使用:
~~~
{between name="id" value="1,10"}
输出内容1
{/between}
~~~
同样,也可以使用`notbetween`标签来判断变量不在某个范围内:
~~~
{notbetween name="id" value="1,10"}
输出内容2
{/notbetween}
~~~
也可以使用`else`标签把两个用法合并,例如:
~~~
{between name="id" value="1,10"}
输出内容1
{else/}
输出内容2
{/between}
~~~
当使用`between`标签的时候,`value`只需要一个区间范围,也就是只支持两个值,后面的值无效,例如
~~~
{between name="id" value="1,3,10"}
输出内容1
{/between}
~~~
实际判断的范围区间是`1~3`,而不是`1~10`,也可以支持字符串判断,例如:
~~~
{between name="id" value="A,Z"}
输出内容1
{/between}
~~~
name属性可以直接使用系统变量,例如:
~~~
{between name="Think.post.id" value="1,5"}
输出内容1
{/between}
~~~
value属性也可以使用变量,例如:
~~~
{between name="id" value="$range"}
输出内容1
{/between}
~~~
变量的值可以是字符串或者数组,还可以支持系统变量。
~~~
{between name="id" value="$Think.get.range"}
输出内容1
{/between}
~~~
## PRESENT/NOTPRESENT标签
present标签用于判断某个变量是否已经定义,用法:
~~~
{present name="name"}
name已经赋值
{/present}
~~~
如果判断没有赋值,可以使用:
~~~
{notpresent name="name"}
name还没有赋值
{/notpresent}
~~~
可以把上面两个标签合并成为:
~~~
{present name="name"}
name已经赋值
{else /}
name还没有赋值
{/present}
~~~
present标签的name属性可以直接使用系统变量,例如:
~~~
{present name="Think.get.name"}
$_GET['name']已经赋值
{/present}
~~~
## EMPTY/NOTEMPTY 标签
empty标签用于判断某个变量是否为空,用法:
~~~
{empty name="name"}
name为空值
{/empty}
~~~
如果判断没有赋值,可以使用:
~~~
{notempty name="name"}
name不为空
{/notempty}
~~~
可以把上面两个标签合并成为:
~~~
{empty name="name"}
name为空
{else /}
name不为空
{/empty}
~~~
name属性可以直接使用系统变量,例如:
~~~
{empty name="Think.get.name"}
$_GET['name']为空值
{/empty}
~~~
## DEFINED 标签
DEFINED标签用于判断某个常量是否有定义,用法如下:
~~~
{defined name="NAME"}
NAME常量已经定义
{/defined}
~~~
> name属性的值要注意严格大小写
如果判断没有被定义,可以使用:
~~~
{notdefined name="NAME"}
NAME常量未定义
{/notdefined}
~~~
可以把上面两个标签合并成为:
~~~
{defined name="NAME"}
NAME常量已经定义
{else /}
NAME常量未定义
{/defined}
~~~
# 原生PHP
Php代码可以和标签在模板文件中混合使用,可以在模板文件里面书写任意的PHP语句代码 ,包括下面两种方式:
## 使用php标签
例如:
~~~
{php}echo 'Hello,world!';{/php}
~~~
我们建议需要使用PHP代码的时候尽量采用php标签,因为原生的PHP语法可能会被配置禁用而导致解析错误。
## 使用原生php代码
~~~
<?php echo 'Hello,world!'; ?>
~~~
注意:php标签或者php代码里面就不能再使用标签(包括普通标签和XML标签)了,因此下面的几种方式都是无效的:
~~~
{php}{eq name='name'value='value'}value{/eq}{/php}
~~~
Php标签里面使用了`eq`标签,因此无效
~~~
{php}if( {$user} != 'ThinkPHP' ) echo 'ThinkPHP' ;{/php}
~~~
Php标签里面使用了`{$user}`普通标签输出变量 ,因此无效。
~~~
{php}if( $user.name != 'ThinkPHP' ) echo 'ThinkPHP' ;{/php}
~~~
Php标签里面使用了`$user.name`点语法变量输出 ,因此无效。
> 简而言之,在PHP标签里面不能再使用PHP本身不支持的代码。
# 定义标签
## ASSIGN标签
ASSIGN标签用于在模板文件中定义变量,用法如下:
~~~
{assign name="var" value="123" /}
~~~
在运行模板的时候,赋值了一个`var`的变量,值是`123`。
name属性支持系统变量,例如:
~~~
{assign name="Think.get.id" value="123" /}
~~~
表示在模板中给`$_GET['id']`赋值了`123`
value属性也支持变量,例如:
~~~
{assign name="var" value="$val" /}
~~~
或者直接把系统变量赋值给var变量,例如:
~~~
{assign name="var" value="$Think.get.name" /}
~~~
相当于,执行了:`$var = $_GET['name'];`
## DEFINE标签
DEFINE标签用于中模板中定义常量,用法如下:
~~~
{define name="MY_DEFINE_NAME" value="3" /}
~~~
在运行模板的时候,就会定义一个`MY_DEFINE_NAME`的常量。
value属性可以支持变量(包括系统变量),例如:
~~~
{define name="MY_DEFINE_NAME" value="$name" /}
~~~
或者
~~~
{define name="MY_DEFINE_NAME" value="$Think.get.name" /}
~~~
