smarty3中对内置函数的改动比较大,添加了许多新的功能:变量声明,表达式,流程控制,函数,数组等。但是建议不要在模版中去使用过于复杂的逻辑,而是要尽量将一些程序设计逻辑写到PH
smarty3中对内置函数的改动比较大,添加了许多新的功能:变量声明,表达式,流程控制,函数,数组等。但是建议不要在模版中去使用过于复杂的逻辑,而是要尽量将一些程序设计逻辑写到PHP中,并在模版中采用非常简单的语法即可调用。通常只在模版中进行一些如变量输出,流程判断及数组遍历等操作即可。
1. 变量声明
在模版中声明变量或用来在模版运行时为模版变量赋值,这是在Smarty3中新增的功能。
使用{assign}
,在模版运行时为模版变量或数组元素赋值 和在赋值时使用一些表达式
{$var=...}
是{assign}
的简写版。其中有三个属性(var,value和scope)和一个选项标签(nocache),其中var和value为必须属性,分别用来设置要分配的值的变量名和分配的值。scope可选,指定分配的变量范围,可以指定parent,root和global三个值。用来设定变量的有效范围。
1.1 用法如下:
{assign var='name' value='brophp'} {*为变量$name赋值上brophp的值*}
{assign "name" "brophp"} {*这是assign函数属性的简写*}
{$name='brophp'} {*assign函数的简写*}
{*定义数组*}
{assign var=foo value=[1,2,3]} {*为变量$foo赋上一个索引数组值*}
{assign var=foo value=['y'=>'yellow','b'=>'blue']} {*为变量$foo赋上一个关联数组值*}
{assign var=foo value=[1,[1,3],4]} {*嵌套声明多维数组*}
{assign var=foo value=$x+$y} {*可以在属性中使用变量*}
{assign var="foo" value="`$foo+$bar`"} {*可以在属性值的字符串中使用变量及表达式*}
{*短变量分配*}
{$foo = $bar+2} {*短变量分配置值的方式*}
{$foo = strlen($bar)} {*PHP函数在变量值中使用*}
{$foo = myfunct($x+$y)*3} {*作为函数参数*}
{$foo.bar=1} {*数组元素的赋值*}
{$foo.bar.baz=1} {*多维数组元素的赋值*}
{$foo[]=1} {*为数组添加新元素*}
{$foo[$x+3]} {*变量作为数组索引*}
{$foo={counter}+3} {*在标签里嵌套标签*}
{$foo="this is message {counter}"} {*在引号里使用标签*}
1.2 参数scope用法
在载入模版中可见被载入模版(即为include进来)的分配变量,在声明变量时可以通过添加scope属性,并通过三个值来为调用的模版指定变量范围。
例如:
{*bar只能在载入模版中常见*}
{assign var="bar" value="value"}
{*用了scope=parent,可以在自己和加载它的模版中可见*}
{assign var="foo" value="something" scope=parent}
{*全局变量在所有模版中可见*}
{assign var=foo value="bar" scope="global"}
{*可以在当前树形结构的"根"中赋值i一个变量。该变量可在所有使用该树形结构的模版中可见*}
{assign var=foo value="bar" scope="root"}
1.3 append用法
可以使用smarty的内置{append}
函数,在模版执行期间建立或追加模版变量数组。
{append var='name' value='Tom'} {*类似于$name[]='Tom'*}
{append var='name' value='Bob' index='first'} {*类似于$name.first='Bob*}
{append var='name' value='Meyer' index='last' scope='parent'} {*类似于$name.last='Meyer*}
2. 流程控制
在smarty3中新增了{for}
和{while}
两个内置函数
2.1 在smarty模版中使用{if}函数处理分支结构
要尽量去使用备用词来代替条件修饰符,这样可以避免在模版中使用和HTML标记符号冲突。Smarty模版中在使用这些修饰词时,它们必须和变量或常量用空格隔开。此外,在PHP标准代码中,必须把条件语句包围在小括号中,而在Smarty中小括号的使用则是可选的,括号主要是用来改变运算符号的优先级别。
一些常见的选择控制结构用法如下:
{if $name eq 'Fred'}
Welcome Sir.
{elseif $name eq 'Wilma'}
Welcome Ma'am.
{else}
Welcom,whatever you are.
{/if}
{if $name eq "Fred" or $name eq 'Wilma'}
...
{/if}
{if $name == 'Fred' || $name == 'Wilma'}
...
{/if}
{if $name=='Fred'||$name=='Wilma'} {*错误的语法,条件符号和变量要用空格隔开*}
...
{/if}
{if($amount <0 or $amount > 1000) and $volume >= #minVolAmt#} {*允许使用圆括号*}
...
{/if}
{if count($var) gt 0} {*可以嵌入函数*}
...
{/if}
{if is_array($foo)} {*数组检查*}
...
{/if}
{if isset($foo)} {*是否为空值检查*}
...
{/if}
{if $var is even} {*测试值为偶数还是基数*}
...
{/if}
{if $var is odd}
...
{/if}
{if $var is not odd}
...
{/if}
{if $var is div by 4} {*测试var能否被4整除*}
...
{/if}
{if $var is even by 2} {*测试发现var是偶数,2个为一组*}
...
{/if}
{if isset($name) && $name == 'Blog'} {*更多{if}例子*}
{*do somthing*}
{elseif $name == $foo}
{* do somthing *}
{/if}
{if is_array($foo) && count($foo) > 0}
{*do a foreach loop*}
{/if}
2.2 在Smarty模版中使用{for}函数处理循环结构
和PHP中的for函数有所差别。在模版中使用{for},{forelse}标签创建一个简单的循环,{for}是一个块函数,需要使用{/for}结束,当循环无迭代时执行{forelse}.支持以下不同的格式。
{for $var=$start to $end}...{/for} {*步长为1的简单循环*}
{for $var=$start to $end step $step}...{/for} {*其他步长循环*}
{for $var=$start to $end max=$val}...{/for} {*设置循环的最大次数*}
其中$var是在{for}函数中定义的一个索引变量,需要给一个初始值作为索引的开始,还需要通过’to’关键字指定一个索引结束的值或变量。也可以通过”step”关键字设置循环的步长,以及通过max中属性设置最大的循环次数。常见的语法如下:
<ul>
{for $foo = 1 to 3} {*设置循环使用变量$foo从1到3,循环3次*}
<li>{$foo}li> {*循环体中的内容被输出3次,$foo的值分别为从1到3*}
ul> {*for循环的结束标记*}
<ul>
{$start=1}
{$end=10}
{for $foo=$start to $end step 2} {*通过step设置循环变量递增的步长,本例设置为2,每次循环递增两次*}
<li>{$foo}li>
{/for}
ul>
<ul>
{for $foo=3 to 1}
<li>{$foo}li>
{forelse}{*循环条件从3到1不成立,会执行forelse语句*}
{forelse}
<li>循环条件不成立li>
{/for}
ul>
2.3 在Smarty模版中使用{while}函数处理循环结构
也是一个块函数,和{if}相似,不过if语句条件成立循环一次,而while则循环多次
例如:
{$foo = 10}
{while $foo gt 0} {*如果变量$foo的值大于10就执行循环体的内容*}
{$foo--}
}
{/while}
3. 声明和调用模版函数
除了可以通过插件机制为smarty模版扩充函数,在smarty3还可以直接使用内置函数{function}
在模版中创建函数,能像调用插件函数一样调用它们
{function}
标签必须包含模版函数名的name属性,该name标签名必须能够调用模版函数。
{function name=menu} {*在模版中声明一个名称为Menu的函数*}
函数体
}
{/function}
{function menu} {*同上,简写形式*}
函数体
{/function}
{menu} {*调用函数menu,和调用插件函数一样调用在模版中自定义的函数*}
在调用函数时,可以通过添加属性为模版中声明的函数传递参数,而声明的函数中不用去接收,直接就可以以变量的形式访问属性参数
{function name=menu} {*在模版中声明的menu函数,并不用去接收参数传递的值*}
{$data}
{$style}
{function}
{menu data=$val hljs-string">"list"
}
可以声明默认的局部变量
{function name=menu level=0 data=$num+1} {*在模版函数声明时,同时声明两个局部变量*}
{$data}
{$level}
{/function}
{menu level=55}
可以通过{call}函数来调用{function}标签定义的模版函数和插件函数
{call name=menu data=$menu} {*调用函数menu,并传递一个data参数*}
{call menu data=$menu} {*简写*}
4. 数组遍历
在Smarty3中,{foreach}
函数的机制全部重新改写,,格式和PHP中的foreach语法基本一样,而{section}
的用法没有变化
{foreach}
可以做{section}
能做的所有事
4.1 在smarty模版中使用{foreach}函数遍历数组
{foreach $arrayvar as $itemvar}...{/foreach}
只遍历数组变量$arrayvar中的值
或
{foreach $arrayvar as $keyvar=>$itemvar}...{/foreach}
遍历数组变量$arrayvar的下标和值
如果使用{foreachelse}
从句,当数组变量无值时执行
{foreach} 属性说明
属性名 |
描述 |
@index |
包含当前数组的下表,开始时为0 |
@iteration |
包含当前虚幻的迭代,总是以1开始,和index不同,每迭代一次值自动加1 |
@first |
当{foreach}循环第一个时first为真 |
@last |
当{foreach}迭代到最后时last为真 |
@show |
用于检测{foreach}循环是否无数据显示,show为布尔值 |
@total |
包含{foreach}循环的总数(整数),可以用在{foreach}里面或后面 |
当然smarty2中的$smarty.foreach.name.property
语法仍然受支持
例如:testSmarty3.php
require_once '../Smarty/Smarty.class.php';
$smarty = new Smarty;
$smarty->left_delimiter="<{";
$smarty->right_delimiter="}>";
$arr1 = array('first'=>'Turing');
$arr2 = array('china'=>'中国','英国','us'=>'美国','日本','法国','德国','俄罗斯');
$arr3 = array('中国','英国','美国','日本','法国','德国','俄罗斯');
$smarty->assign('nameList',$arr1);
$smarty->assign('str','hahah');
$smarty->assign('arr2',$arr2);
$smarty->assign('arr3',$arr3);
$smarty->display('testSmarty3.html');
testSmarty3.html
<h2>foreach使用h2>
<h4>@iteration,@index,@first,@last,@totalh4>
$arr2 = array('china'=>'中国','英国','us'=>'美国','日本','法国',
'德国','俄罗斯','');
<table border="1" cellspacing="0">
<{foreach $arr2 as $k=>$v}>
<{if $v@first}>
<tr>
<td>@iterationtd>
<td>@indextd>
<td>$ktd>
<td>$vtd>
tr>
<{/if}>
<tr>
<td><{$v@iteration}>td>
<td><{$v@index}>td>
<td><{$k}>td>
<td><{$v}>td>
tr>
<{if $v@last}>
<tr><td colspan="4">总共循环<{$v@total}>次td>tr>
<{/if}>
<{foreachelse}>
$arr2为空
<{/foreach}>
<{if $v@show}>
<tr>
<td colspan="4">数据来源:最暖一天td>
tr>
<{/if}>
table>
4.2 在smarty模版中使用{section}函数遍历数组
{section}属性:
属性名 |
描述 |
类型 |
默认值 |
name |
指定该循环的名称,当需要section循环内输出变量时,必须在变量后加上中括号包含着name变量,为必要参数 |
字符串 |
无 |
loop |
决定循环次数的变量名称,与数组变量同名,必要参数 |
数组变量 |
无 |
start |
确定循环开始执行的索引位置.如果是负数,则从尾部算起,例如有七个元素,则start为-2时,是从数组索引为5开始算起,如果超过循环数组的限制,则会被自动调整为最接近的合法值 |
整型 |
1 |
step |
决定了循环的步长,如果为负数,则从后向前遍历 |
整型 |
1 |
max |
循环最大执行次数 |
整型 |
数组长度 |
show |
决定是否显示该循环。可以使用这个参数进行调试 |
布尔类型 |
true |
{section}
只能循环下标从0开始的索引数组。可以使用{sectionelse}
,当loop属性为空时输出该区域内容。
在section中通过如下方式调用循环中的变量:
$smarty.section.sectionname.varname
其中{$smarty.section}
是Smarty的保留变量,sectionname即在section标记中指定的name属性值,而varname则是在section中被调用的特定变量名称。
section循环区域中可以调用的变量
变量名 |
描述 |
index |
用于显示当前循环的索引 |
index_prev |
用于显示上一个循环索引值。循环开始时,此值为-1 |
index_next |
用于显示下一个循环索引值。循环执行到最后一次时,此值仍然比当前索引值大1 |
iteration |
显示当前循环次数 |
first |
当前循环在第一次时为true |
last |
当前循环在最后一次时为false |
rownum |
iteration别名 |
loop |
用于显示该循环上一次循环时的索引值,该值可以用于循环内部或循环结束后 |
show |
true或false.如果设置为false,则该循环将不显示,如果指定了sectionelse子句,则该子句是否显示也取决于改值 |
total |
显示循环总数,可以在循环中使用,也可以结束后使用 |
将上面{foreach}
例子改写:
<h2>section使用h2>
<h4>@iteration,@index,@first,@last,@totalh4>
$arr3 = array('中国','英国','美国','日本','法国',
'德国','俄罗斯','');
<table border="1" cellspacing="0">
<{section loop=$arr3 name='ls'}>
<{if $smarty.section.ls.first}>
<tr>
<td>@iterationtd>
<td>@indextd>
<td>下标td>
<td>值td>
tr>
<{/if}>
<tr>
<td><{$smarty.section.ls.iteration}>td>
<td><{$smarty.section.ls.index}>td>
<td><{$smarty.section.ls.index}>td>
<td><{$arr3[ls]}>td>
tr>
<{if $smarty.section.ls.last}>
<tr><td colspan="4">总共循环<{$smarty.section.ls.total}>次td>tr>
<{/if}>
<{sectionelse}>
$arr2为空
<{/section}>
<{if $smarty.section.ls.show}>
<tr>
<td colspan="4">数据来源:最暖一天td>
tr>
<{/if}>
table>
5. Smarty提供的其他内置函数
{block}
,{nocache}
将在后面的博客中提到。
smarty2中的{php}
和{include_php}
在模版中插入PHP程序,和模版使用规则相违背,已经在Smarty3中弃用。
{strip},{literal},{ldelim},{rdelim}
和{insert}
都有其他更好的方法代替,前面的博客已经部分提到
**{include}**
在多个模版中有相同的内容要输出,则可以将相同的部分在独立的模版中定义,然后在需要的模版中进行导入。在模版中使用{include}
在档期看模版中包含其他模版,必须使用file属性指明模版资源位置。
例如:头部文件header.tpl和尾部文件爱你footer.tpl都是独立的模版文件,希望每个模版中都导入这两个文件。则:
{include file='header.tpl'} {*导入头部模版文件*}
这是当前模版中的主体内容部分
{include file='footer.tpl'} {*导入尾部模版文件*}
include有两个比较实用的特性:
- 可以在
{include}
标记中传入可选的assign属性,将导入的子模版内容不在当前模版中输出,而是赋给由assign属性指定的变量
{include file='header.tpl' assign="header"} {*模版header.tpl中的全部内容都赋给变量header*}
- 可以在导入子模版的同时向其传递各种属性。以此方式传递给子模版的任何属性。只能在被导入的文件中使用,不能用于模版的其他位置。如果传递的属性名在被包含模版中有同名变量,则该变量被传递的属性替代。
{include file='header.tpl' title="main menu" table_bgcolor="#ccc"} {*在包含header.tpl时将这两个属性传递给它*}
这是当前模版文件中的主体部分
{include file="footer.tpl" logo="logo.gif"}