smarty的Foreach和Section(转)

在 Smarty 样板中,我们要重复一个区块有两种方式: foreach 及 section 。而在程序中我们则要 assign 一个数组,这个数组中可以包含数组数组。就像下面这个例子: 首先我们来看 PHP 程序是如何写的: test2.php:
复制PHP内容到剪贴板
PHP代码:
<?php require "main.php"; $array1 = array(1 => "苹果", 2 => "菠萝", 3 => "香蕉", 4 => "芭乐"); $tpl->assign("array1", $array1); $array2 = array( array("index1" => "data1-1", "index2" => "data1-2", "index3" => "data1-3"), array("index1" => "data2-1", "index2" => "data2-2", "index3" => "data2-3"), array("index1" => "data3-1", "index2" => "data3-2", "index3" => "data3-3"), array("index1" => "data4-1", "index2" => "data4-2", "index3" => "data4-3"), array("index1" => "data5-1", "index2" => "data5-2", "index3" => "data5-3")); $tpl->assign("array2", $array2); $tpl->display("test2.htm"); ?>
而模版的写法如下: templates/test2.htm:
复制PHP内容到剪贴板
PHP代码:
<html> <head> <meta http-equiv="Content-Type" c> <title>测试重复区块</title> </head> <body> <pre> 利用 foreach 来呈现 array1 <{foreach item=item1 from=$array1}> <{$item1}> <{/foreach}> 利用 section 来呈现 array1 <{section name=sec1 loop=$array1}> <{$array1[sec1]}> <{/section}> 利用 foreach 来呈现 array2 <{foreach item=index2 from=$array2}> <{foreach key=key2 item=item2 from=$index2}> <{$key2}>: <{$item2}> <{/foreach}> <{/foreach}> 利用 section 来呈现 array2 <{section name=sec2 loop=$array2}> index1: <{$array2[sec2].index1}> index2: <{$array2[sec2].index2}> index3: <{$array2[sec2].index3}> <{/section}> </pre> </body> </html>
执行上例后,我们发现不管是 foreach 或 section 两个执行结果是一样的。那么两者到底有何不同呢? 第一个差别很明显,就是foreach 要以巢状处理的方式来呈现我们所 assign 的两层数组变量,而 section 则以「主数组[循环名称].子数组索引」即可将整个数组呈现出来。由此可知, Smarty 在模版中的 foreach 和 PHP 中的 foreach 是一样的;而 section 则是 Smarty 为了处理如上列的数组变量所发展出来的叙述。当然 section 的功能还不只如此,除了下一节所谈到的巢状资料呈现外,官方手册中也提供了好几个 section 的应用范例。 不过要注意的是,丢给 section 的数组索引必须是从 0 开始的正整数,即 0, 1, 2, 3, ...。如果您的数组索引不是从 0 开始的正整数,那么就得改用 foreach 来呈现您的资料。您可以参考官方讨论区中的此篇讨论,其中探讨了 section 和 foreach 的用法。 巢状资料的呈现 模版引擎里最令人伤脑筋的大概就是巢状资料的呈现吧,许多著名的模版引擎都会特意强调这点,不过这对 Smarty 来说却是小儿科。 最常见到的巢状资料,就算论譠程序中的讨论主题区吧。假设要呈现的结果如下:
引用:
公告区 站务公告 文学专区 好书介绍 奇文共赏 计算机专区 硬件外围 软件讨论
程序中我们先以静态资料为例: test3.php:
复制PHP内容到剪贴板
PHP代码:
<?php require "main.php"; $forum = array( array("category_id" => 1, "category_name" => "公告区", "topic" => array( array("topic_id" => 1, "topic_name" => "站务公告") ) ), array("category_id" => 2, "category_name" => "文学专区", "topic" => array( array("topic_id" => 2, "topic_name" => "好书介绍"), array("topic_id" => 3, "topic_name" => "奇文共赏") ) ), array("category_id" => 3, "category_name" => "计算机专区", "topic" => array( array("topic_id" => 4, "topic_name" => "硬件外围"), array("topic_id" => 5, "topic_name" => "软件讨论") ) ) ); $tpl->assign("forum", $forum); $tpl->display("test3.htm"); ?>
模版的写法如下: templates/test3.htm:
复制PHP内容到剪贴板
PHP代码:
<html> <head> <title>巢状循环测试</title> </head> <body> <table width="200" border="0" align="center" cellpadding="3" cellspacing="0"> <{section name=sec1 loop=$forum}> <tr> <td colspan="2"><{$forum[sec1].category_name}></td> </tr> <{section name=sec2 loop=$forum[sec1].topic}> <tr> <td width="25"> </td> <td width="164"><{$forum[sec1].topic[sec2].topic_name}></td> </tr> <{/section}> <{/section}> </table> </body> </html>
执行的结果就像笔者举的例子一样。 因此呢,在程序中我们只要想办法把所要重复值一层一层的塞到数组中,再利用 <{第一层数组[循环1].第二层数组[循环2].第三层数组[循环3]. ... .数组索引}> 这样的方式来显示每一个巢状循环中的值。至于用什么方法呢?下一节使用数据库时我们再提。 转换数据库中的资料 上面提到如何显示巢状循环,而实际上应用时我们的资料可能是从数据库中抓取出来的,所以我们就得想办法把数据库的资料变成上述的多重数组的形式。这里笔者用一个 DB 类别来抓取数据库中的资料,您可以自行用您喜欢的方法。 我们只修改 PHP 程序,模版还是上面那个 (这就是模版引擎的好处~),其中 $db 这个对象假设已经在 main.php 中建立好了,而且抓出来的资料就是上面的例子。 test3.php:
复制PHP内容到剪贴板
PHP代码:
<?php require "main.php"; // 先建立第一层数组 $category = array(); $db->setSQL($SQL1, 'CATEGORY'); if (!$db->query('CATEGORY')) die($db->error()); // 抓取第一层循环的资料 while ($item_category = $db->fetchAssoc('CATEGORY')) { // 建立第二层数组 $topic = array(); $db->setSQL(sprintf($SQL2, $item_category['category_id']), 'TOPIC'); if (!$db->query('TOPIC')) die($db->error()); // 抓取第二层循环的资料 while ($item_topic = $db->fetchAssoc('TOPIC')) { // 把抓取的数据推入第二层数组中 array_push($topic, $item_topic); } // 把第二层数组指定为第一层数组所抓取的数据中的一个成员 $item_category['topic'] = $topic; // 把第一层数据推入第一层数组中 array_push($category, $item_category); } $tpl->assign("forum", $category); $tpl->display("test3.htm"); ?>
在数据库抓取一笔资料后,我们得到的是一个包含该笔数据的数组。透过 while 叙述及 array_push 函式,我们将数据库中的资料一笔一笔塞到数组里。如果您只用到单层循环,就把第二层循环 (红色的部份) 去掉即可。 决定内容是否显示 要决定是否显示内容,我们可以使用 if 这个语法来做选择。例如如果使用者已经登入的话,我们的模版就可以这样写:
引用:
<{if $is_login == true}> 显示使用者操作选单 <{else}> 显示输入帐号和密码的窗体 <{/if}>
要注意的是,「==」号两边一定要各留至少一个空格符,否则 Smarty 会无法解析。 if 语法一般的应用可以参照官方使用说明,所以笔者在这里就不详加介绍了。不过笔者发现了一个有趣的应用:常常会看到程序里要产生这样的一个表格: (数字代表的是资料集的顺序)
引用:
1 2 3 4 5 6 7 8
这个笔者称之为「横向重复表格」。它的特色和传统的纵向重复不同,前几节我们看到的重复表格都是从上而下,一列只有一笔资料。而横向重复表格则可以横向 地在一列中产生 n 笔资料后,再换下一列,直到整个循环结束。要达到这样的功能,最简单的方式只需要 section 和 if 搭配即可。 我们来看看下面这个例子: test4.php:
复制PHP内容到剪贴板
PHP代码:
<?php require "main.php"; $my_array = array( array("value" => "0"), array("value" => "1"), array("value" => "2"), array("value" => "3"), array("value" => "4"), array("value" => "5"), array("value" => "6"), array("value" => "7"), array("value" => "8"), array("value" => "9")); $tpl->assign("my_array", $my_array); $tpl->display('test4.htm'); ?>
模版的写法如下: templates/test4.htm:
复制PHP内容到剪贴板
PHP代码:
<html> <head> <title>横向重复表格测试</title> </head> <body> <table width="500" border="1" cellspacing="0" cellpadding="3"> <tr> <{section name=sec1 loop=$my_array}> <td><{$my_array[sec1].value}></td> <{if $smarty.section.sec1.rownum is div by 2}> </tr> <tr> <{/if}> <{/section}> </tr> </table> </body> </html>
重点在于 $smarty.section.sec1.rownum 这个 Smarty 变量,在 section 循环中这个变量会取得从 1 开始的索引值,所以当 rownum 能被 2 除尽时,就输出 </tr><tr> 使表格换列 (注意!是 </tr> 在前面<tr> 在后面) 。因此数字 2 就是我们在一列中想要呈现的资料笔数。各位可以由此去变化其它不同的呈现方式。 加载外部内容 我们可以在模版内加载 PHP 程序代码或是另一个子模版,分别是使用 include_php 及 include 这两个 Smarty 模版语法; include_php 笔者较少用,使用方式可以查询官方手册,这里不再叙述。 在使用 include 时,我们可以预先加载子模版,或是动态加载子模版。预先加载通常使用在有共同的文件标头及版权宣告;而动态加载则可以用在统一的框架页,而进一步达到如 Winamp 般可换 Skin 。当然这两种我们也可以混用,视状况而定。 我们来看看下面这个例子: test5.php:
复制PHP内容到剪贴板
PHP代码:
<?php require "main.php"; $tpl->assign("title", "Include 测试"); $tpl->assign("content", "这是模版 2 中的变量"); $tpl->assign("dyn_page", "test5_3.htm"); $tpl->display('test5_1.htm'); ?>
模版 1 的写法如下: templates/test5_1.htm:
复制PHP内容到剪贴板
PHP代码:
<html> <head> <meta http-equiv="Content-Type" c> <title><{$title}></title> </head> <body> <{include file="test5_2.htm"}><br /> <{include file=$dyn_page}> <{include file="test5_4.htm" custom_var="自订变量的内容"}> </body> </html>
模版 2 的写法如下: templates/test5_2.htm: <{$content}> 模版 3 的写法如下: templates/test5_3.htm: 这是模版 3 的内容 模版 4 的写法如下: templates/test5_4.htm: <{$custom_var}> 这里注意几个重点:1. 模版的位置都是以先前定义的 template_dir 为基准;2. 所有 include 进来的子模版中,其变量也会被解译。;3. include 中可以用「变量名称=变量内容」来指定引含进来的模版中所包含的变量,如同上面模版 4 的做法。

“smarty的Foreach和Section(转)”   No comments

No comments yet.

Leave a comment:

XHTML: You can use these tags: <a href="" title=""> <b> <blockquote cite=""> <em> <i> <strong> <p> <br><br />