PHP smarty 模板 嵌套FOREACH section-foreach详解PHP SMARTY
前面我们曾经简单提及Smarty用于处理循环的方案-section,同时在上一篇的内建函数列表中大家应该也看到了还有一个处理循环的方案-foreach。这次我们就来比较一下这两个方案的异同点并详细分析它们的用法。
首先我们来看一下它们在语法上的异同:
脚本:
$custid = array(1000,1001,1002);
$smarty->assign('custid',$custid);
foreach模板:
{* 该例将输出数组 $custid 中的所有元素的值 *}
{foreach from=$custid item=curr_id}
id: {$curr_id}<br>
{/foreach}
section模板:
{* 该例同样输出数组 $custid 中的所有元素的值 *}
{section name=customer loop=$custid}
id: {$custid[customer]}<br>
{/section}
foreach的语法可以概括为:将一个数组assign给from=后面的变量名,数组元素会依次赋给item=后面的变量名,要显示元素则只需要输出item变量即可;
section的语法则是:将一个数组assign给loop=后面的变量名,然后由name=后面的变量名来作为一个下标(指针),要显示元素则需要输出一个数组形式{$custid[customer]};
看到这里估计大家会产生一个疑惑,foreach简单明了,容易理解,section显得就有些复杂,为什么呢?我们先看下两者的说明:
foreach 用于处理简单数组(数组中的元素的类型一致),它的格式比 section 简单许多,缺点是只能处理简单数组。
foreach 必须和 /foreach 成对使用,且必须指定 from 和 item 属性。
name 属性可以任意指定(字母、数字和下划线的组合)。
foreach 可以嵌套,但必须保证嵌套中的 foreach 名称唯一。
from 属性(通常是数组)决定循环的次数。
section 标签必须设置 name 和 loop 属性。
名称可以是包含字母、数字和下划线的任意组合。
可以嵌套但必须保证嵌套的 name 唯一。
变量 loop (通常是数组)决定循环执行的次数。
当需要在 section 循环内输出变量时,必须在变量后加上中括号包含着的 name 变量。
通过比较我们可以发现,section的loop和foreach的from比较象;section的name和foreach的item比较象,似乎区别仅在于foreach只能处理简单数组这一句。那么我们就来演示下什么情况是foreach处理不了的。
先看一个多数组的例子:
#p#副标题#e#
脚本:
$custid = array(1000,1001,1002);
$name = array('john','jack','jane');
$smarty->assign('custid',$custid);
$smarty->assign('name',$name);
模板:
{* 该例同时混合输出数组 $custid和$name中的所有元素的值 *}
{section name=customer loop=$custid}
id: {$custid[customer]}<br>
name: {$name[customer]}<br>
{/section}
这个例子显示了section的name和foreach的item是不同的,要想用foreach获得同样的效果就没这么方便了。
对于多维数组的处理,两者倒是没什么区别:
脚本:
$customer[] = array('custid'=>1000,'name'=>'john','address'=>'253 N 45th');
$customer[] = array('custid'=>1001,'name'=>'jack','address'=>'417 Mulberry ln');
$customer[] = array('custid'=>1002,'name'=>'jane','address'=>'5605 apple st'); $smarty->assign('customer',$customer);
foreach 模板:
{foreach from=$customer item=curr_item}
id: {$curr_item.custid}<br>
name: {$curr_item.name}<br>
address: {$curr_item.address}<br>
<p>
{/foreach}
section模板:
{section name=cust loop=$customer}
id: {$customer[cust].custid}<br>
name: {$customer[cust].name}<br>
address: {$customer[cust].address}<br>
<p>
{/section}
显示结果是一样的。
#p#副标题#e#
下面来看一下嵌套的情况,我们为上一例的数组增加一个contact_type,值为一个联系方式的数组,在foreach中应该如下嵌套:
脚本:
<?php
$customer[] = array('custid' => 1000, 'name' => 'yangtao1', 'address' => '253 N 45th', 'contact_type' => array('home phone' => '555-555-5555', 'cell phone' => '555-555-5555', 'e-mail' => 'yangtao1@awzsr.com'));
$customer[] = array('custid' => 1001, 'name' => 'yangtao2', 'address' => '417 Mulberry ln', 'contact_type' => array('home phone' => '444-444-4444', 'cell phone' => '444-444-4444', 'e-mail' => 'yangtao2@awzsr.com'));
$customer[] = array('custid' => 1002, 'name' => 'yangtao3', 'address' => '5605 apple st', 'contact_type' => array('home phone' => '666-666-6666', 'cell phone' => '666-666-6666', 'e-mail' => 'yangtao3@awzsr.com'));
$smarty -> assign('customer', $customer);
?>
foreach 模板:
{foreach from=$customer item=curr_item}
id: {$curr_item.custid}<br>
name: {$curr_item.name}<br>
address: {$curr_item.address}<br>
{foreach from=$curr_item.contact_type item=contact key=key}
{$key}: {$contact}<br>
{/foreach}
<p>
{/foreach}
显示结果如下:
id: 1000
name: john
address: 253 N 45th
home phone: 555-555-5555
cell phone: 555-555-5555
e-mail: yangtao1@awzsr.com
id: 1001
name: jack
address: 417 Mulberry ln
home phone: 444-444-4444
cell phone: 444-444-4444
e-mail: yangtao2@awzsr.com
id: 1002
name: jane
address: 5605 apple st
home phone: 666-666-6666
cell phone: 666-666-6666
e-mail: yangtao3@awzsr.com
(本例中我们顺便看到了key的用法,key就是每个循环的元素键值)
#p#副标题#e#
在section中由于书写格式的不同,脚本有些差异:
脚本:
$customer[] = array('custid'=>1000,'name'=>'john','address'=>'253 N 45th');
$customer[] = array('custid'=>1001,'name'=>'jack','address'=>'417 Mulberry ln');
$customer[] = array('custid'=>1002,'name'=>'jane','address'=>'5605 apple st');
$contact_type[] = array('home phone','cell phone','e-mail');
$contact_type[] = array('home phone','cell phone','e-mail');
$contact_type[] = array('home phone','cell phone','e-mail');
$contact_info[] = array('555-555-5555','555-555-5555','john@awzsr.com');
$contact_info[] = array('444-444-4444','444-444-4444','jack@awzsr.com');
$contact_info[] = array('666-666-6666','666-666-6666','jane@awzsr.com');
$smarty->assign('contact_type',$contact_type);
$smarty->assign('contact_info',$contact_info);
$smarty->assign('customer',$customer);
section 模板:
{section name=cust loop=$customer}
id: {$customer[cust].custid}<br>
name: {$customer[cust].name}<br>
address: {$customer[cust].address}<br>
{section name=contact loop=$contact_type[cust]}
{$contact_type[cust][contact]}: {$contact_info[cust][contact]}<br>
{/section}
<p>
{/section}
显示结果和上面的foreach结果是一样的。
两种嵌套方式,看上去section的繁琐一些,foreach简单明了,其实不然,完全是因为两者所使用的数据的格式不同,如果您能够控制数据的格式,可以在使用时考虑foreach例子中的形式,如果您只能得到section例子中这样的数据格式,那就只能使用section例子的写法了。
最后我们来了解一下这两个循环的一些变量。
#p#副标题#e#
foreach 循环有自己的变量名,使用该变量名可以访问该循环。使用方法为{$smarty.foreach.foreachname.varname},同样,section就用{$smarty.section.sectionname.varname}。下面我们来对照着学习两者的变量,先学两者都有的:
0、前面已经提到的有:name、foreach的from相当于section的loop,这里就不再介绍了。
1、iteration 用于显示循环的次数,从1开始
脚本:
$customer[] = array('custid'=>1000);
$customer[] = array('custid'=>1001);
$customer[] = array('custid'=>1002);
$smarty->assign('customer',$customer);
foreach 模板:
{foreach from=$customer item=curr_item name=cust}
id: {$curr_item.custid}<br>
current loop iteration: {$smarty.foreach.cust.iteration}<br>
<p>
{/foreach}
section 模板:
{section name=cust loop=$customer}
id: {$customer[cust].custid}<br>
current loop iteration: {$smarty.section.cust.iteration}<br>
<p>
{/section}
看例子,两者没什么区别,就是foreach的name不是必需的,所以别忘了设定。
#p#副标题#e#
2、first 当前 foreach 或 section 循环第一次执行时 first 被设置成 true
脚本:
同上
foreach 模板:
{foreach from=$customer item=curr_item name=cust}
id: {$curr_item.custid}<br>
{if $smarty.foreach.cust.first}This is the first row{/if}<br>
<p>
{/foreach}
section 模板:
{section name=cust loop=$customer}
id: {$customer[cust].custid}<br>
{if $smarty.section.cust.first}This is the first row{/if}<br>
<p>
{/section}
显示结果在第一个元素行会多输出This is the first row,其余行就不会。
3、last 当前 foreach 或 section 循环执行到最后一遍时 last 被设置成 true脚本:
同上
foreach 模板:
{foreach from=$customer item=curr_item name=cust}
id: {$curr_item.custid}<br>
{if $smarty.foreach.cust.last}This is the last row{/if}<br>
<p>
{/foreach}
section 模板:
{section name=cust loop=$customer}
id: {$customer[cust].custid}<br>
{if $smarty.section.cust.last}This is the last row{/if}<br>
<p>
{/section}
#p#副标题#e#
4、show 该循环是否显示,show 取值为布尔值 true 或 false。如果设置为 false,该循环将不显示。如果指定了foreachelse或 sectionelse 子句,该字句是否显示也取决于该值
5、total 用于显示循环执行的次数,可以在循环中或循环执行后调用脚本:
同上
foreach 模板:
{foreach from=$customer item=curr_item name=cust}
id: {$curr_item.custid}<br>
{$smarty.foreach.cust.total}<br>
<p>
{/foreach}
{$smarty.foreach.cust.total}<br>
section 模板:
{section name=cust loop=$customer}
id: {$customer[cust].custid}<br>
{$smarty.section.cust.total}<br>
<p>
{/section}
{$smarty.section.cust.total}<br>
共有的参数就是这些,下面是foreach独有的两个参数:
1、item 当前处理元素的变量名称
2、key 当前处理元素的键名
前文已有介绍,不再赘述。
下面是section独有的参数:
1、index 用于显示当前循环的索引,从0开始(如果指定了start属性,那么由该值开始),每次加1(如果指定了step属性,那么由该值决定)。脚本:
同上
section 模板:
{section name=cust loop=$customer}
{$smarty.section.cust.index} id: {$customer[cust].custid}<br>
<p>
{/section}
显示结果:
0 id: 1000
1 id: 1001
2 id: 1002
2、index_prev 用于显示上一个循环索引值。循环开始时,此值为-1。脚本:
同上
section 模板:
{section name=cust loop=$customer}
{$smarty.section.cust.index_prev} id: {$customer[cust].custid}<br>
<p>
{/section}
显示结果:
-1 id: 1000
0 id: 1001
1 id: 1002
3、index_next 用于显示下一个循环索引值。循环执行到最后一次时,此值仍然比当前索引值大1(如果指定了step,取决于此值)。脚本:
同上
section 模板:
{section name=cust loop=$customer}
{$smarty.section.cust.index_next} id: {$customer[cust].custid}<br>
<p>
{/section}
显示结果:
1 id: 1000
2 id: 1001
3 id: 1002
#p#副标题#e#
4、rownum 用于显示循环的次数。该属性是iteration的别名,两者等同。
5、loop 用于显示该循环最后的索引值。该值可以用于循环内部或循环结束后。如果未设置start和step,则和total值相等。脚本:
同上
section 模板:
{section name=cust loop=$customer step=2}
{$smarty.section.cust.loop} id: {$customer[cust].custid}<br>
<p>
{/section}
{$smarty.section.cust.total}
显示结果:
3 id: 1000
3 id: 1002
2
6、start 循环执行的初始位置。如果该值为负数,开始位置从数组的尾部算起。例如:如果数组中有7个元素,指定start为-2,那么指向当前数组的索引为5
7、step 该值决定循环的步长。例如指定step=2将只遍历下标为0、2、4等的元素。如果step为负值,那么遍历数组的时候从后向前遍历。
8、max 设定循环最多执行几次。