复制PHP内容到剪贴板
而模版的写法如下:
templates/test2.htm:
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");
?>
复制PHP内容到剪贴板
执行上例后,我们发现不管是 foreach 或 section 两个执行结果是一样的。那么两者到底有何不同呢?
第一个差别很明显,就是foreach 要以巢状处理的方式来呈现我们所 assign 的两层数组变量,而 section 则以「主数组[循环名称].子数组索引」即可将整个数组呈现出来。由此可知, Smarty 在模版中的 foreach 和 PHP 中的 foreach 是一样的;而 section 则是 Smarty 为了处理如上列的数组变量所发展出来的叙述。当然 section 的功能还不只如此,除了下一节所谈到的巢状资料呈现外,官方手册中也提供了好几个 section 的应用范例。
不过要注意的是,丢给 section 的数组索引必须是从 0 开始的正整数,即 0, 1, 2, 3, ...。如果您的数组索引不是从 0 开始的正整数,那么就得改用 foreach 来呈现您的资料。您可以参考官方讨论区中的此篇讨论,其中探讨了 section 和 foreach 的用法。
巢状资料的呈现
模版引擎里最令人伤脑筋的大概就是巢状资料的呈现吧,许多著名的模版引擎都会特意强调这点,不过这对 Smarty 来说却是小儿科。
最常见到的巢状资料,就算论譠程序中的讨论主题区吧。假设要呈现的结果如下:
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>
引用:
公告区 站务公告 文学专区 好书介绍 奇文共赏 计算机专区 硬件外围 软件讨论
复制PHP内容到剪贴板
模版的写法如下:
templates/test3.htm:
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");
?>
复制PHP内容到剪贴板
执行的结果就像笔者举的例子一样。
因此呢,在程序中我们只要想办法把所要重复值一层一层的塞到数组中,再利用 <{第一层数组[循环1].第二层数组[循环2].第三层数组[循环3]. ... .数组索引}> 这样的方式来显示每一个巢状循环中的值。至于用什么方法呢?下一节使用数据库时我们再提。
转换数据库中的资料
上面提到如何显示巢状循环,而实际上应用时我们的资料可能是从数据库中抓取出来的,所以我们就得想办法把数据库的资料变成上述的多重数组的形式。这里笔者用一个 DB 类别来抓取数据库中的资料,您可以自行用您喜欢的方法。
我们只修改 PHP 程序,模版还是上面那个 (这就是模版引擎的好处~),其中 $db 这个对象假设已经在 main.php 中建立好了,而且抓出来的资料就是上面的例子。
test3.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>
复制PHP内容到剪贴板
在数据库抓取一笔资料后,我们得到的是一个包含该笔数据的数组。透过 while 叙述及 array_push 函式,我们将数据库中的资料一笔一笔塞到数组里。如果您只用到单层循环,就把第二层循环 (红色的部份) 去掉即可。
决定内容是否显示
要决定是否显示内容,我们可以使用 if 这个语法来做选择。例如如果使用者已经登入的话,我们的模版就可以这样写:
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");
?>
引用:
<{if $is_login == true}> 显示使用者操作选单 <{else}> 显示输入帐号和密码的窗体 <{/if}>
引用:
1 2 3 4 5 6 7 8
复制PHP内容到剪贴板
模版的写法如下:
templates/test4.htm:
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');
?>
复制PHP内容到剪贴板
重点在于 $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代码:
<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>
复制PHP内容到剪贴板
模版 1 的写法如下:
templates/test5_1.htm:
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');
?>
复制PHP内容到剪贴板
模版 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 的做法。 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>