Thinkphp 模板/内置标签
来自:https://blog.csdn.net/qq_42176520/category_7824704.html
模板替换
在进行模板渲染之前,系统还会对读取的模板内容进行一些特殊字符串替换操作,也就是实现了模板输出的替换和过滤。该替换操作仅针对内置的模版引擎。
这个机制可以使得模板文件的定义更加方便,默认的替换规则有:
__ROOT__: 会替换成当前网站的地址(不含域名)
__APP__: 会替换成当前应用的URL地址 (不含域名)
__MODULE__:会替换成当前模块的URL地址 (不含域名)
__CONTROLLER__(__或者__URL__ 兼容考虑): 会替换成当前控制器的URL地址(不含域名)
__ACTION__:会替换成当前操作的URL地址 (不含域名)
__SELF__: 会替换成当前的页面URL
__PUBLIC__:会被替换成当前网站的公共目录 通常是 /Public
默认情况下,模板替换只会替换模板文件的特殊字符串,不会替换动态数据中的输出的内容。
注意这些特殊的字符串是严格区别大小写的,并且这些特殊字符串的替换规则是可以更改或者增加的,我们只需要在应用或者模块的配置文件中配置TMPL_PARSE_STRING就可以完成。如果有相同的数组索引,就会更改系统的默认规则。例如:
'TMPL_PARSE_STRING' =>array( '__PUBLIC__' => '/Common', // 更改默认的/Public 替换规则 '__JS__' => '/Public/JS/', // 增加新的JS类库路径替换规则 '__UPLOAD__' => '/Uploads', // 增加新的上传路径替换规则 )
有了模板替换规则后,模板中的所有__PUBLIC__
字符串都会被替换,那如果确实需要输出__PUBLIC__
字符串到模板呢,我们可以通过增加替换规则的方式,例如:
'TMPL_PARSE_STRING' =>array( '--PUBLIC--' => '__PUBLIC__', // 采用新规则输出`__PUBLIC__`字符串 )
这样增加替换规则后,如果我们要在模板中使用__PUBLIC__
字符串,只需要在模板中添加--PUBLIC--,其他替换字符串的输出方式类似。
修改定界符
模板文件可以包含普通模板标签和XML模板标签,标签的定界符都可以重新配置。
普通标签
内置模板引擎的普通模板标签默认以{ 和 } 作为开始和结束标识,并且在开始标记紧跟标签的定义,如果之间有空格或者换行则被视为非模板标签直接输出。 例如:{$name}
、{$vo.name}
、{$vo['name']|strtoupper}
都属于普通模板标签。
要更改普遍模板的起始标签和结束标签,请使用下面的配置参数:
TMPL_L_DELIM //模板引擎普通标签开始标记 TMPL_R_DELIM //模板引擎普通标签结束标记
例如在项目配置文件中增加下面的配置:
'TMPL_L_DELIM' => '<{', 'TMPL_R_DELIM' => '}>'
普通标签的定界符就被修改了,原来的 {$name}
和 {$vo.name}
必须使用 <{$name}>
和 <{$vo.name}>
才能生效了。
如果你定制了普通标签的定界符,记得修改下默认的系统模板。
XML标签
普通模板标签主要用于模板变量输出和模板注释。如果要使用其它功能,请使用XML模板标签。XML模板标签可以用于模板变量输出、文件包含、条件控制、循环输出等功能,而且完全可以自己扩展功能。如果你觉得XML标签无法在正在使用的编辑器里面无法编辑,还可以更改XML标签库的起始和结束标签,请修改下面的配置参数:
TAGLIB_BEGIN //标签库标签开始标签 TAGLIB_END //标签库标签结束标记
例如在项目配置文件中增加下面的配置:
'TAGLIB_BEGIN'=>'[', 'TAGLIB_END'=>']',
原来的
<eq name="name" value="value"> 相等 <else/> 不相等 </eq>
就必须改成
[eq name="name" value="value"]
相等
[else/]
不相等
[/eq]
注意:XML标签和普通标签的定界符不能冲突,否则会导致解析错误。
变量输出
在模板中输出变量的方法很简单,例如,在控制器中我们给模板变量赋值:
$name = 'ThinkPHP'; $this->assign('name',$name); $this->display(); //然后就可以在模板中使用: Hello,{$name}! //模板编译后的结果就是: Hello,<?php echo($name);?>! //运行结果 Hello,ThinkPHP!
注意模板标签的{
和$
之间不能有任何的空格,否则标签无效。所以,Hello,{ $name}!
将不会正常输出name变量,而是直接保持不变输出: Hello,{ $name}!
普通标签默认开始标记是{
,结束标记是 }
。也可以通过设置TMPL_L_DELIM
和TMPL_R_DELIM
进行更改。
模板标签的变量输出根据变量类型有所区别,刚才我们输出的是字符串变量,如果是数组变量:
$data['name'] = 'ThinkPHP'; $data['email'] = 'thinkphp@qq.com'; $this->assign('data',$data); //在模板中我们可以用下面的方式输出: Name:{$data.name} Email:{$data.email} 或者用下面的方式也是有效: Name:{$data['name']} Email:{$data['email']} //当我们要输出多维数组的时候,往往要采用后面一种方式。
如果data变量是一个对象(并且包含有name和email两个属性),那么可以用下面的方式输出:
Name:{$data:name} Email:{$data:email} //或者 Name:{$data->name} Email:{$data->email}
三元运算
模板可以支持三元运算符,例如:
{$status?'正常':'错误'}
{$info['status']?$info['msg']:$info['error']}
注意:三元运算符中暂时不支持点语法。
运算符
运算符 | 使用示例 |
---|---|
+ | {$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'])} //正确的
默认值输出
我们可以给变量输出提供默认值,例如:
{$user.nickname|default="这家伙很懒,什么也没留下"}
对系统变量依然可以支持默认值输出,例如:
{$Think.get.name|default="名称为空"}
默认值和函数可以同时使用,例如:
{$Think.get.name|getName|default="名称为空"} {$Think.get.name|getName|default="名称为空"}应该改成{$Think.get.name|default="名称为空"|getName}
使用函数
对模板输出变量使用函数,可以使用:
{$data.name|md5} <!-- 编译后的结果是:--> <?php echo (md5($data['name'])); ?>
如果函数有多个参数需要调用,则使用:
{$create_time|date="y-m-d",###} <!-- 编译后的结果是:--> <?php echo (date("y-m-d",$create_time)); ?>
{$create_time|date="y-m-d",###}表示date函数传入两个参数,每个参数用逗号分割,这里第一个参数是y-m-d
,第二个参数是前面要输出的create_time
变量,因为该变量是第二个参数,因此需要用###标识变量位置。
如果前面输出的变量在后面定义的函数的第一个参数,则可以直接使用:
{$data.name|substr=0,3} <!--表示输出 --> <?php echo (substr($data['name'],0,3)); ?> <!--虽然也可以使用: --> {$data.name|substr=###,0,3} <!--但完全没用这个必要。 -->
还可以支持多个函数过滤,多个函数之间用“|”分割即可,例如:
{$name|md5|strtoupper|substr=0,3} <!--编译后的结果是: --> <?php echo (substr(strtoupper(md5($name)),0,3)); ?>
函数会按照从左到右的顺序依次调用。
如果你觉得这样写起来比较麻烦,也可以直接这样写:
{:substr(strtoupper(md5($name)),0,3)}
变量输出使用的函数可以支持内置的PHP函数或者用户自定义函数,甚至是静态方法。
IF标签
用法示例:
<if condition="($name eq 1) OR ($name gt 100) "> value1 <elseif condition="$name eq 2"/>value2 <else /> value3 </if>
在condition属性中可以支持eq等判断表达式,同上面的比较标签,但是不支持带有”>”、”<”等符号的用法,因为会混淆模板解析,所以下面的用法是错误的:
<if condition="$id < 5 ">value1 <else /> value2 </if>
可以试一下修改模板标签为{},是否这样就可以支持”>”、”<”等符号
除此之外,我们可以在condition属性里面使用php代码,例如:
<if condition="strtoupper($user['name']) neq 'THINKPHP'">ThinkPHP <else /> other Framework </if>
condition属性可以支持点语法和对象语法,例如: 自动判断user变量是数组还是对象
<if condition="$user.name neq 'ThinkPHP'">ThinkPHP <else /> other Framework </if>
或者知道user变量是对象
<if condition="$user:name neq 'ThinkPHP'">ThinkPHP <else /> other Framework </if>
由于if标签的condition属性里面基本上使用的是php语法,尽可能使用判断标签和Switch标签会更加简洁,原则上来说,能够用switch和比较标签解决的尽量不用if标签完成。因为switch和比较标签可以使用变量调节器和系统变量。如果某些特殊的要求下面,IF标签仍然无法满足要求的话,可以使用原生php代码或者PHP标签来直接书写代码。
Volist标签
volist标签通常用于查询数据集(select方法)的结果输出,通常模型的select方法返回的结果是一个二维数组,可以直接使用volist标签进行输出。 在控制器中首先对模版赋值:
$User = M('User'); $list = $User->limit(10)->select(); $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>
支持输出查询结果中的部分数据,例如输出其中的第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>
模板中可以直接使用函数设定数据集,而不需要在控制器中给模板变量赋值传入数据集变量,如:
<volist name=":fun('arg')" id="vo"> {$vo.name} </volist>
Foreach标签
foreach标签类似与volist标签,只是更加简单,没有太多额外的属性,例如:
<foreach name="list" item="vo"> {$vo.id}:{$vo.name} </foreach>
name表示数据源,item表示循环变量。
可以输出索引 {$key},如下:
<foreach name="list" item="vo" > {$key}|{$vo} </foreach>
也可以定义索引的变量名
<foreach name="list" item="vo" key="k" > {$k}|{$vo} </foreach>
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; }
包含文件
在当前模版文件中包含其他的模版文件使用include标签,标签用法:
<include file='模版表达式或者模版文件1,模版表达式或者模版文件2,...' />
使用模版表达式
模版表达式的定义规则为:模块@主题/控制器/操作
例如:
可能为:
<include file="Public/header" /> // 包含头部模版header <include file="Public/menu" /> // 包含菜单模版menu <include file="Blue/Public/menu" /> // 包含blue主题下面的menu模版
<include file="Public/header,Public/menu" />
注意,包含模版文件并不会自动调用控制器的方法,也就是说包含的其他模版文件中的变量赋值需要在当前操作中完成。
使用模版文件
可以直接包含一个模版文件名(包含完整路径),例如:
<include file="./Application/Home/View/default/Public/header.html" />
传入参数
无论你使用什么方式包含外部模板,Include标签支持在包含文件的同时传入参数,例如,下面的例子我们在包含header模板的时候传入了title和keywords变量:
<include file="Public/header" title="ThinkPHP框架" keywords="开源WEB开发框架" />
就可以在包含的header.html文件里面使用title和keywords变量,如下:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>[title]</title> <meta name="keywords" content="[keywords]" /> </head>
注意:由于模板解析的特点,从入口模板开始解析,如果外部模板有所更改,模板引擎并不会重新编译模板,除非在调试模式下或者缓存已经过期。如果部署模式下修改了包含的外部模板文件后,需要把模块的缓存目录清空,否则无法生效。
Switch标签
用法:
<switch name="变量" > <case value="值1" break="0或1">输出内容1</case> <case value="值2">输出内容2</case> <default />默认情况 </switch>
使用方法如下:
<switch name="User.level"> <case value="1">value1</case> <case value="2">value2</case> <default />default </switch>
其中name属性可以使用函数以及系统变量,例如:
<switch name="Think.get.userId|abs"> <case value="1">admin</case> <default />default </switch>
对于case的value属性可以支持多个条件的判断,使用”|”进行分割,例如:
<switch name="Think.get.type"> <case value="gif|png|jpg">图像格式</case> <default />其他格式 </switch>
表示如果$_GET["type"] 是gif、png或者jpg的话,就判断为图像格式。
Case标签还有一个break属性,表示是否需要break,默认是会自动添加break,如果不要break,可以使用:
<switch name="Think.get.userId|abs"> <case value="1" break="0">admin</case> <case value="2">admin</case> <default />default </switch>
也可以对case的value属性使用变量,例如:
<switch name="User.userId"> <case value="$adminId">admin</case> <case value="$memberId">member</case> <default />default </switch>
使用变量方式的情况下,不再支持多个条件的同时判断。
范围判断标签 IN和NOTIN
范围判断标签包括in notin between notbetween四个标签,都用于判断变量是否中某个范围。
IN和NOTIN
用法: 假设我们在后台控制器中给id赋值为1,在前端可以使用in标签来判断模板变量是否在某个范围内
<!--后台--> $id = 1; $this->assign('id',$id); <!--前端--> <in name="id" value="1,2,3">id在范围内</in> <!--输出:id在范围内-->
如果判断不在某个范围内,可以使用: 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>
更多的系统变量用法可以参考系统变量部分。
value属性也可以使用变量,例如:
<in name="id" value="$range">id在范围内</in>
$range变量可以是数组,也可以是以逗号分隔的字符串。
value属性还可以使用系统变量,例如:
<in name="id" value="$Think.post.ids">id在范围内</in>
BETWEEN 和 NOTBETWEEN
可以使用between标签来判断变量是否在某个区间范围内,使用notbetween标签来判断变量不在某个范围内,也可以使用else标签把两个用法合并,例如:
<!--1--> <between name="id" value="1,10">输出内容1</between> <!--2--> <notbetween name="id" value="1,10">输出内容2</notbetween> <!--3--> <between name="id" value="1,10"> 输出内容1 <else/> 输出内容2 </between>
当使用between标签的时候,value只需要一个区间范围,也就是只支持两个值,后面的值无效,例如
<!-- 实际判断的范围区间是1~3,而不是1~10 --> <between name="id" value="1,3,10"> 输出内容1 </between>
,也可以支持字符串判断,例如:
<between name="id" value="A,Z"> 输出内容1</between>
name属性可以直接使用系统变量,value属性也可以使用变量,变量的值可以是字符串或者数组,还可以支持系统变量。例如:
<between name="Think.post.id" value="1,5">输出内容1</between> <between name="id" value="$range">输出内容1</between> <between name="id" value="$Think.get.range">输出内容1</between>
RANGE
也可以直接使用range标签,替换前面的判断用法:
<range name="id" value="1,2,3" type="in">输出内容1</range>
其中type属性的值可以用in/notin/between/notbetween,其它属性的用法和IN或者BETWEEN一致。