11.6 流程控制
Smarty提供了几种可以控制模板内容输出的结构,包括能够按条件判断决定输出内容的if…elseif…else结构,也有迭代处理传入数据的foreach和section结构。本节将介绍这些在Smarty模板中使用的控制结构。
11.6.1 条件选择结构if…else
Smarty模板中的{if}语句和PHP中的if语句一样灵活易用,并增加了几个特性以适宜模板引擎。Smarty中{if}必须和{/if}成对出现,当然也可以使用{else}和{elseif}子句。另外,在{if}中可以使用表11-7中给出的全部条件修饰词。
Smarty模板中在使用这些修饰词时,它们必须和变量或常量用空格隔开。此外,在PHP标准代码中,必须把条件语句包围在小括号中,而在Smarty中小括号的使用则是可选的。一些常见的选择控制结构用法如下所示。
{if $name eq "Fred"} {* 判断变量$name的值是否为Fred *} Welcome Sir. {* 如果条件成立则输出这个区块的代码 *} {elseif $name eq "Wilma"} {* 否则判断变量$name的值是否为Wilma *} Welcome Ma'am. {* 如果条件成立则输出这个区块的代码 *} {else} {* 否则从句,在其他条件都不成立时执行 *} Welcome, whatever you are. {* 如果条件成立则输出这个区块的代码 *} {/if} {* 是条件控制的关闭标记,if必须成对出现*} {if $name eq "Fred" or $name eq "Wilma"} {* 使用逻辑运算符"or"的一个例子 *} ... {* 如果条件成立则输出这个区块的代码 *} {/if} {* 是条件控制的关闭标记,if必须成对出现*} {if $name == "Fred" || $name == "Wilma"} {* 和上面的例子一样,"or"和"||"没有区别 *} ... {* 如果条件成立则输出这个区块的代码 *} {/if} {* 是条件控制的关闭标记,if必须成对出现*} {if $name=="Fred" || $name=="Wilma"} {* 错误的语法,条件符号和变量要用空格隔开*} ... {* 如果条件成立则输出这个区块的代码 *} {/if} {* 是条件控制的关闭标记,if必须成对出现*}
11.6.2 foreach
在Smarty模板中,可以使用foreach或section两种方式重复一个区块。而在模板中则需要从PHP中分配过来一个数组,这个数组也可以是多维数组。foreach标记的作用与PHP中的foreach相同,但它们的使用语法大不相同,因为在模板中增加了几个特性以适应模板引擎。它的语法格式虽然比较简单,但只能用来处理简单数组。在模板中{foreach}必须和{/foreach}成对使用,它有4个参数,其中from和item两个是必要的,如表11-8所示:
参数名 | 描述 | 类型 | 默认值 |
from | 待循环数组的名称,该属性决定循环的次数,必要参数 | 数组变量 | 无 |
item | 确定当前元素的变量名称,必要参数 | 字符串 | 无 |
key | 当前处理元素的键名,可选参数 | 字符串 | 无 |
name | 该循环的名称,用于访问该循环,这个名是任意的,可选参数 | 字符串 | 无 |
也可以在模板中嵌套使用foreach遍历二维数组,但必须保证嵌套中的foreach名称唯一。此外,在使用foreach遍历数组时与下标无关,所以在模板中关联数组和索引数组都可以使用foreach遍历。
考虑一个使用foreach遍历数组的示例。假设PHP从数据库中读取了一张表的所有记录,并保存在一个声明好的二维数组中,而且需要将这个数组中的数据在网页中显示。可以在脚本文件index.php中,直接声明一个二维数据保存三个人的联系信息,并通过Smarty引擎分配给模板文件。代码如下所示。
<?php require "libs/Smarty.class.php"; //包含Smarty类库 $smarty = new Smarty(); //创建Smarty类的对象 $contact=array( //声明一个保存三个联系人信息的二维数组 array('name'=>'王某','fax'=>'1','email'=>'w@HBSI.net','phone'=>'4'), array('name'=>'张某','fax'=>'2','email'=>'z@HBSI.net','phone'=>'5'), array('name'=>'李某','fax'=>'3','email'=>'l@HBSI.net','phone'=>'6')); $smarty->assign('contact', $contact); //将关联数组$contact分配到模板中使用 $smarty->display('index.tpl'); //查找模板替换并输出 ?>
创建一个模板文件index.tpl,使用双层foreach嵌套遍历从PHP中分配的二维数组,并以表格的形式在网页中输出。代码如下所示。
<html> <head> <title>联系人信息列表</title> </head> <body> <table border="1" width="80%" align="center"> <caption><h1>联系人信息</h1></caption> <tr> <th>姓名</th><th>传真</th><th>电子邮件</th><th>联系电话</th> </tr> {foreach from=$contact item=row} {* 外层foreach遍历数组$contact *} <tr> {* 输出表格的行开始标记 *} {foreach from=$row item=col} {* 内层foreach遍历数组$row *} <td>{$col}</td> {* 以表格形式输出数组中的每个数据 *} {/foreach} {* 内层foreach区块结束标记 *} </tr> {* 输出表格的行结束标记 *} {/foreach} {* 外层foreach区域的结束标记 *} </table> </body> </html>
在Smarty模板中还为foreach标记提供了一个扩展标记foreachelse,这个语句在from变量没有值的时候被执行,就是在数组为空时foreachelse标记可以生成某个候选结果。在模板中,foreachelse标记不能独自使用,一定要与foreach一起使用。而且foreachelse不需要结束标记,它嵌入在foreach中,与elseif嵌入在if语句中很类似。一个使用foreachelse的模板示例如下。
{foreach key=key item=value from=$array} {* 使用foreach遍历数组$array中的键和值 *} {$key} => {$item} <br> {* 在模板中输出数组$array中元素的键和值对 *} {foreachelse} {* foreachelse在数组$array没有值的时候被执行*} <p>数组$array中没有任何值</p> {* 如果看到这条语句,说明数组中没有任何数据*} {/foreach} {* foreach需要成对出现,是foreach的结束标记 *}
11.6.3 section
先看一段PHP代码:
$pc_id = array(1000,1001,1002); $smarty->assign('pc_id',$pc_id);
section模板:
{* 该例同样输出数组 $pc_id 中的所有元素的值 *} {section name=i loop=$pc_id} id: {$pc_id[i]}<br> {/section}
section用于遍历数组中的数据,section标签必须成对出现,必须设置name和loop属性,名称可以是包含字母、数字和下划线的任意组合,可以嵌套但必须保证嵌套的name唯一,变量loop(通常是数组)决定循环执行的次数,当需要在section循环内输出变量时,必须在变量后加上中括号包含着的name变量,sectionelse当loop变量无值时被执行。
section语法参数:
{section name = name loop = $varName[, start = $start, step = $step, max = $max, show = true]}
name:section的名称,不用加$。
$loop:要循环的变量,在程序中要使用assign对这个变量进行操作。
$start:开始循环的下标,循环下标默认由0开始。
$step:每次循环时下标的增数。
$max:最大循环下标。
$show:boolean类型,决定是否对这个块进行显示,默认为true。
这里有个名词需要说明。
循环下标:实际它的英文名称为index,是索引的意思,这里将它译成“下标”,主要是为了好理解。它表示在显示这个循环块时当前的循环索引,默认从0开始,受$start的影响,如果将$start设为5,它也将从5开始计数,在模板设计部分使用过它,这是当前{section}的一个属性,调用方式为Smarty.section.sectionName.index,这里的sectionName指的是函数原型中的name属性。
{section}块具有的属性值分别如下。
(1)index:前边介绍的“循环下标”,默认为0。
(2)index_prev:当前下标的前一个值,默认为–1。
(3)index_next:当前下标的下一个值,默认为1。
(4)first:是否为第一个循环。
(5)last:是否为最后一个循环。
(6)iteration:循环次数。
(7)rownum:当前的行号,iteration的另一个别名。
(8)loop:最后一个循环号,可用在section块后统计section的循环次数。
(9)total:循环次数,可用在section块后统计循环次数。
(10)show:在函数的声明中有它,用于判断section是否显示。