转换数据库中的资料 上面提到如何显示巢状循环,而实际上应用时我们的资料可能是从数据库中抓取出来的,所以我们就得想办法把数据库的资料变成上述的多重数组的形式。这里笔者用一个 DB 类别来抓取数据库中的资料,您可以自行用您喜欢的方法。
我们只修改 PHP 程序,模版还是上面那个 (这就是模版引擎的好处~),其中 $db 这个对象假设已经在 main.php 中建立好了,而且抓出来的资料就是上面的例子。
test3.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
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:
<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
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:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5">
<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 的做法。