使用例子:
{$webTitle|md5|strtoupper|substr=0,3}
编译后的PHP代码就是:
<?php echo (substr(strtoupper(md5($webTitle)),0,3)); ?>
注意函数的定义和使用顺序的对应关系,通常来说函数的第一个参数就是前面的变量或者前一个函数使用的结果,如果你的变量并不是函数的第一个参数,需要使用定位符号,例如:
{$create_time|date="y-m-d",###}
编译后的PHP是:
<?php echo (date("y-m-d",$create_time)); ?>
函数的使用没有个数限制,但是可以允许配置TMPL_DENY_FUNC_LIST定义禁用函数列表,系统默认禁用了exit和echo函数,以防止破坏模板输出,我们也可以增加额外的定义,例如:
TMPL_DENY_FUNC_LIST=>"echo,exit,halt"
多个函数之间使用半角逗号分隔即可。
?
并且还提供了在模板文件中直接调用函数的快捷方法,无需通过模板变量,包括两种方式:
1、执行方法并输出返回值:
格式:{:function(…)}
例如,输出U方法的返回值:
{:U('User/insert')}
编译后的PHP代码是
<?php echo U('User/insert');?>
?
2、执行方法但不输出:
格式:{~function(…)}
例如,调用say_hello函数:
{~say_hello('ThinkPHP')}
编译后的PHP代码是:
<?php say_hello('ThinkPHP');?>
系统变量
除了常规变量的输出外,模板引擎还支持系统变量和系统常量、以及系统特殊变量的输出。它们的输出不需要事先赋值给某个模板变量。系统变量的输出必须以$Think. 打头,并且仍然可以支持使用函数。
1、系统变量:包括server、session、post、get、request、cookie
{$Think.server.script_name } // 输出$_SERVER变量
{$Think.session.session_id|md5 } // 输出$_SESSION变量
{$Think.get.pageNumber } // 输出$_GET变量
{$Think.cookie.name } // 输出$_COOKIE变量
支持输出$_SERVER、$_ENV、 $_POST、 $_GET、 $_REQUEST、$_SESSION和 $_COOKIE变量。后面的server、cookie、config不区分大小写,但是变量区分大小写。例如:
{$Think.server.script_name }和{$Think.SERVER.script_name }等效
SESSION 、COOKIE还支持二维数组的输出,例如:
{$Think.CONFIG.user.user_name}
{$Think.session.user.user_name}
系统不支持三维以上的数组输出,请使用下面的方式输出。
?
以上方式还可以写成:
{$_SERVER.script_name } // 输出$_SERVER变量
{$_SESSION.session_id|md5 } // 输出$_SESSION变量
{$_GET.pageNumber } // 输出$_GET变量
{$_COOKIE.name } // 输出$_COOKIE变量
?
2、系统常量 :使用$Think.const 输出
{$Think.const.__SELF__ }
{$Think.const.MODULE_NAME }
或者直接使用
{$Think.__SELF__ }
{$Think.MODULE_NAME }
?
3、特殊变量 :由ThinkPHP系统内部定义的常量
{$Think.version } //版本
{$Think.now } //现在时间
{$Think.template|basename } //模板页面
{$Think.LDELIM } //模板标签起始符号
{$Think.RDELIM } //模板标签结束符号
?
4、配置参数 :输出项目的配置参数值
{$Think.config.db_charset}
输出的值和C('db_charset') 的返回结果是一样的。
也可以输出二维的配置参数,例如:
{$Think.config.user.user_name}
?
5、语言变量:输出项目的当前语言定义值
{$Think.lang.page_error}
输出的值和L('page_error')的返回结果是一样的。
快捷输出
为了使得模板定义更加简洁,系统还支持一些常用的变量输出快捷标签,包括:
} //输出Session变量 和 {$Think.session.var} 等效
{#var} //输出Cookie变量 和 {$Think.cookie.var} 等效
{&var} //输出配置参数 和 {$Think.config.var} 等效
{%var} //输出语言变量 和 {$Think.lang.var} 等效
{.var} //输出GET变量 和 {$Think.get.var} 等效
{^var} //输出POST变量 和{$Think.post.var} 等效
{*var} //输出常量和 {$Think.const.var} 等效
如果需要输出二维数组,例如 要输出$_SESSION[‘var1’][‘var2’]的值 快捷输出可以使用:
} 的方式
同理
{#var1.var2}
可以输出 $_COOKIE[‘var1’][‘var2’]的值。
必须注意的是:快捷输出的变量不支持函数的使用。
所以,下面的用法是错误的:
{#var|strlen}
默认值输出
如果输出的模板变量没有值,但是我们需要在显示的时候赋予一个默认值的话,可以使用default语法,格式:
{$变量|default="默认值"}
这里的default不是函数,而是系统的一个语法规则,例如:
{$user.nickname|default="这家伙很懒,什么也没留下"}
对系统变量的输出也可以支持默认值,例如:
{$Think.post.name|default="名称为空"}
因为快捷输出不支持使用函数,所以也不支持默认值,默认值支持Html语法。
包含文件
可以使用Include标签来包含外部的模板文件,使用方法如下:
1、 使用完整文件名包含
格式:<include file="完整模板文件名" />
例如:
<include file="./Tpl/default/Public/header.html" />
这种情况下,模板文件名必须包含后缀。使用完整文件名包含的时候,特别要注意文件包含指的是服务器端包含,而不是包含一个URL地址,也就是说file参数的写法是服务器端的路径,如果使用相对路径的话,是基于项目的入口文件位置。
?
2、包含当前模块的其他操作模板文件
格式:<include file="操作名" />
例如 导入当前模块下面的read操作模版:
<include file="read" />
操作模板无需带后缀。
?
3、 包含其他模块的操作模板
格式:<include file="模块名:操作名" />
例如,包含Public模块的header操作模版:
<include file="Public:header" />
?
4、包含其他模板主题的模块操作模板
格式:<include file="主题名@模块名:操作名" />
例如,包含blue主题的User模块的read操作模版:
<include file="" />
?
5、 用变量控制要导入的模版
格式:<include file="$变量名" />
例如
<include file="$tplName" />
给$tplName赋不同的值就可以包含不同的模板文件,变量的值的用法和上面的用法相同。
?
6、使用快捷方式包含文件
格式:{include:模板文件规则}
其中的模板文件规则可以使用上面提到的5种方式。
注意:由于模板解析的特点,从入口模板开始解析,如果外部模板有所更改,模板引擎并不会重新编译模板,除非缓存已经过期。如果修改了包含的外部模板文件后,需要把模块的缓存目录清空,否则无法生效。
导入文件
传统方式的导入外部JS和CSS文件的方法是直接在模板文件使用:
<script type='text/javascript' src='/Public/Js/Util/Array.js'>
<link rel="stylesheet" type="text/css" href="/App/Tpl/default/Public/css/style.css" />
?
系统提供了专门的标签来简化上面的导入:
第一个是import标签 ,导入方式采用类似ThinkPHP的import函数的命名空间方式,例如:
<import type='js' file="Js.Util.Array" />
Type属性默认是js, 所以下面的效果是相同的:
<import file="Js.Util.Array" />
还可以支持多个文件批量导入,例如:
<import file="Js.Util.Array,Js.Util.Date" />
导入外部CSS文件必须指定type属性的值,例如:
<import type='css' file="Css.common" />
上面的方式默认的import的起始路径是网站的Public目录,如果需要指定其他的目录,可以使用basepath属性,例如:
<import file="Js.Util.Array" basepath="./Common" />
?
第二个是load标签,通过文件方式导入当前项目的公共JS或者CSS
例如:
<load href="../Public/Js/Common.js" />
<load href="../Public/Css/common.css" />
在href属性中可以使用特殊模板标签替换,例如:
<load href="__PUBLIC__/Js/Common.js" />
Load标签可以无需指定type属性,系统会自动根据后缀自动判断。
系统还提供了两个标签别名js和css 用法和load一致,例如:
<js href="__PUBLIC__/Js/Common.js" />
<css href="../Public/Css/common.css" />
?
另外,系统提供了普通标签的方式加载外部js和css文件。
{load: __PUBLIC__/Js/Common.js}
{load: ../Public/Css/common.css }
Volist标签
Volist标签主要用于在模板中循环输出数据集或者多维数组。
通常模型的select和findall方法返回的结果是一个二维数组,可以直接使用volist标签进行输出。
在Action中首先对模版赋值:
$User = M('User');
$list = $User->select();
$this->assign('list',$list);
?
在模版定义如下,循环输出用户的编号和姓名:
<volist name="list" id="vo">
{$vo.id}
{$vo.name}
</volist>
Volist标签的name属性表示模板赋值的变量名称,因此不可随意在模板文件中改变。id表示当前的循环变量,可以随意指定,但确保不要和name属性冲突,例如:
<volist name="list" id="data">
{$data.id}
{$data.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" 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还有一个别名iterate,用法和volist是一样。
Foreach标签
foreach标签也是用于循环输出
<foreach name="list" item="vo" >
{$vo.id}
{$vo.name}
</foreach>
Foreach标签相对比volist标签简洁,没有volist标签那么多的功能。优势是可以对对象进行遍历输出,而volist标签通常是用于输出数组。
Switch标签
模板引擎支持Switch标签,格式为:
<switch name="变量" >
<case value="值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的value属性使用变量,例如:
<switch name="User.userId">
<case value="$adminId">admin</case>
<case value="$memberId">member</case>
<default />default
</switch>
使用变量方式的情况下,不再支持多个条件的同时判断。
比较标签
模板引擎提供了丰富的判断标签,比较标签的用法是:
<比较标签 name="变量" value="值">内容</比较标签>
系统支持的比较标签以及所表示的含义分别是:
2 eq或者 equal:等于
2 neq 或者notequal:不等于
2 gt:大于
2 egt:大于等于
2 lt:小于
2 elt:小于等于
2 heq:恒等于
2 nheq:不恒等于
他们的用法基本是一致的,区别在于判断的条件不同。
例如,要求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属性的值就是上面列出的比较标签名称
Range标签
Range标签用于判断某个变量是否在某个范围之内,包括in、notin和range三个标签。
可以使用in标签来判断模板变量是否在某个范围内,例如:
<in name="id" value="1,2,3" >输出内容1</in>
如果判断不再某个范围内,可以使用:
<notin name="id" value="1,2,3" >输出内容2</notin>
可以把上面两个标签合并成为:
<in name="id" value="1,2,3" >输出内容1<else/>输出内容2</in>
Value属性的值可以使用变量,例如:
<in name="id" value="$var" >输出内容1</in>
变量的值可以是字符串或者数组,都可以完成范围判断。
也可以直接使用range标签,替换in和notin的用法:
<range name="id" value="1,2,3" type="in" >输出内容1</range>
其中type属性的值可以用in或者notin。
Present标签
可以使用present标签来判断模板变量是否已经赋值,例如:
<present name="name">name已经赋值</present>
如果判断没有赋值,可以使用:
<notpresent name="name">name还没有赋值</notpresent>
可以把上面两个标签合并成为:
<present name="name">name已经赋值<else /> name还没有赋值</present>
Empty标签
可以使用empty标签判断模板变量是否为空,例如:
<empty name="name">name为空值</empty>
如果判断没有赋值,可以使用:
<notempty name="name">name不为空</notempty>
可以把上面两个标签合并成为:
<empty name="name">name为空<else /> name不为空</empty>
Defined标签
可以使用defined标签判断常量是否已经有定义,例如:
<defined name="NAME">NAME常量已经定义</defined>
如果判断没有被定义,可以使用:
<notdefined name="NAME">NAME常量未定义</notdefined>
可以把上面两个标签合并成为:
<defined name="NAME">NAME常量已经定义<else /> NAME常量未定义</defined>
IF标签
如果觉得上面的标签都无法满足条件判断要求的话,我们还可以使用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>
必须改成:
<if condition="$id lt 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(及其别名iterate)、switch、if、elseif、else、foreach、compare(包括所有的比较标签)、(not)present、(not)empty、(not)defined等标签都可以嵌套使用。例如:
<volist name="list" id="vo">
<volist name="vo['sub']" id="sub">
{$sub.name}
</volist>
</volist>
上面的标签可以用于输出双重循环。
默认的嵌套层次是3级,所以嵌套层次不能超过3层,如果需要更多的层次可以指定TAG_NESTED_LEVEL配置参数。
使用PHP代码
Php代码可以和标签在模板文件中混合使用,可以在模板文件里面书写任意的PHP语句代码 ,包括下面两种方式:
第一种是使用php标签:
<php>echo 'Hello,world!';</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本身不支持的代码。
原样输出
可以使用literal标签来防止模板标签被解析,例如:
<literal>
<if condition="$name eq 1 "> value1
<elseif condition="$name eq 2" />value2
<else /> value3
</if>
</literal>
上面的if标签被literal标签包含,因此if标签里面的内容并不会被模板引擎解析,而是保持原样输出。
Literal标签可以用于页面的JS代码外面,确保JS代码中的某些用法和模板引擎不产生混淆。
模板注释
模板支持注释功能,该注释文字在最终页面不会显示,仅供模板制作人员参考和识别。
格式:{/* 注释内容 */ } 或 {// 注释内容 }
说明:在显示页面的时候不会显示模板注释,仅供模板制作的时候参考。
注意{和注释标记之间不能有空格。
例如:
{// 这是模板注释内容 }
{/* 这是模板
注释内容*/ }
模板注释支持多行可以。模板注释在生成编译缓存文件后会自动删除,这一点和Html的注释不同。
引入标签库
前面我们所讲述的标签用法都是内置的标签库或者内置模板的用法,事实上,内置模板引擎的标签库是可以无限扩展和增加标签的,一旦你扩展和使用了新的标签库,就必须要告诉模板当前要使用的标签库名称,否则不会自动导入,防止以后标签库大量扩展后增加解析工作量,导入标签库使用tagLib标签。
格式:<tagLib name="标签库1[,标签库2,…]" />
可以同时导入多个标签库,用逗号分隔。
例如:
<tagLib name="html" />
表示在当前模板文件需要引入html标签库。要引入标签库必须确保有Html标签库的定义文件和解析类库(如何扩展这种方式请参考前面的标签库扩展部分)。Cx标签库内置导入,无需使用taglib标签导入。
引入后,html标签库的所有标签在当前模板页面中都可以使用了。外部导入的标签库必须使用标签库前缀的xml标签,避免两个不同的标签库中存在同名的标签定义,例如(假设Html标签库中已经有定义select和link标签):
<html:select options='name' selected='value' />
<html:link href='/path/to/common.js' />
标签库使用的时候忽略大小写,因此下面的方式一样有效:
<HTML:LINK HREF='/path/to/common.js' />
?
如果你的每个模板页面都需要加载Html标签库的话,也可以通过配置直接预先加载Html标签库。
'TAGLIB_PRE_LOAD' => 'html' ,
如果有多个标签库需要预先加载的话,用逗号分隔。定义之后,每个模板页面都可以直接使用:
<html:select options='name' selected='value' />
而不需手动引入Html标签库。
?
假设你确信Html标签库无论在现在还是将来都不会和系统内置的标签库存在相同的标签,那么可以配置TAGLIB_BUILD_IN的值把Html标签库作为内置标签库引入,例如:
'TAGLIB_BUILD_IN' => 'cx,html' ,
这样,也无需在模板文件页面引入Html标签库了,并且可以不带前缀直接使用Html标签库的标签:
<select options='name' selected='value' />
注意,cx标签库是系统内置标签库,不能删除定义。
修改定界符
模板文件可以包含普通模板标签和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模板标签,ThinkPHP包含了一个基于XML和TagLib技术的模板标签,包含了普通模板有的功能,并且有一些方面的增强和补充,更重要的一点是新的标签库模板技术更加具有扩展性。新的TagLib标签库具有命名空间功能,ThinkPHP框架内置了CX标签库。如果你觉得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标签和普通标签的定界符不能冲突,否则会导致解析错误。
XML模板标签可以用于模板变量输出、文件包含、模板注释、条件控制、循环输出等功能,而且完全可以自己扩展功能。