《PHP与MySQL程序设计(第3版)》――19.5 Smarty的表现逻辑
对Smarty等模板引擎也有一些批评,批评者通常抱怨说引擎的特性集集成了某种程度的逻辑。毕竟模板引擎的主旨是完全分离表现层和逻辑层,对不对?虽然这是我们的理想,但不一定是最可行的解决方案。例如,如果没有某种迭代逻辑,如何以某种格式输出MySQL结果集?要得到十全十美的解决方案是不可能的。面对这个两难处境,Smarty开发人员在引擎中集成了一些简单但非常有效的应用程序逻辑。这似乎是一种理想的折衷,因为网站设计人员通常不是编程人员(反之亦然)。
本节将学习Smarty的表现特性:变量修饰符、控制结构和语句。首先对注释做一个简要介绍。
19.5.1 注释
本章剩余部分在必要时都会使用注释。因此,看来有必要先来介绍Smarty的注释语法。注释包围在定界标记{*和*}之间,可以包括一行或多行。以下是一个合法的Smarty注释:
19.5.2 变量修饰符
在第9章已经看到,PHP提供了很多函数,这些函数能够以你能想象到的任何方式处理文本。但是,你可能想在表现层中使用这样一些特性――例如,确保文章作者的姓和名在文章描述中首字母大写。为此,Smarty开发人员在库中集成了许多表现特有的功能。本节将介绍一些比较有趣的特性。
在概要介绍之前,有必要先说明Smarty的一个不太传统的变量修饰符语法。当然,定界符用来指示所请求的变量输出,而在输出前,需要修饰的变量值后面可以跟一个竖线,再后面是修饰符命令,如下:
你将看到在本节介绍修饰符时会反复使用这个语法。
1.首字母大小
capitalize函数把变量中所有单词的首字母变为大写。示例如下:
article.tpl模板包含:
返回如下:
2.单词计数
count_words函数统计变量中的单词总数。示例如下:
article.tpl模板包含:
这会返回:
3.格式化日期
date_format函数是PHPstrftime()函数的包装器,它能将可以被strftime()解析的任何日期/时间格式字符串转换为某种特殊格式。因为格式化标志在手册和第12章中已做介绍,所以这里没必要重复列出。下面是一个使用示例:
article.tpl模板包含:
这会返回:
4.赋默认值
当应用层没有返回值时,default函数为指示特定变量的默认值提供了一种简单的方式。例如:
default.tpl模板包含:
这会返回:
5.删除标记符
strip_tags函数删除变量字符串中的标记符。例如:
striptags.tpl模板包含:
这会返回:
6.截取字符串
truncate函数将变量字符串截取为指定数量的字符。虽然默认为80个字符,但可以通过提供一个输入参数(如下例所示)来改变截取的长度。可以指定一个字符串(可选),追加到截取后的字符串后面,如省略号(...)。此外,可以指定到达指定的字符数限制后立即截取,或者还需要考虑单词的边界(参数为TRUE,则按确切的限制截取,FALSE则截取到达到限制后最近的单词边界)。例如:
truncate.tpl模板包含:
这会返回:
19.5.3 控制结构
Smarty提供了几种控制结构,能够按条件和迭代处理传入的数据。本节将介绍这些结构。
1.if函数
Smarty的if函数与PHP语言中的if函数相同。与PHP一样,可以使用一些条件限定符,如下所列:
下面是一个简单示例:
再考虑另一个示例。假设希望根据月份插入某个消息。如下示例使用了条件限定符、elseif以及else语句来完成这个任务:
注意,把条件语句包围在小括号中是可选的,但在标准PHP代码中这却是必需的。
2.foreach函数
foreach函数的作用与PHP语句中的命令相同。但如下所示,其语法大不相同。它有4个参数,其中两个是必要的。
qfrom。这个必要参数指定目标数组的名。
qitem。这个必要参数确定当前元素的名。
qkey。这个可选参数确定当前键的名。
qname。这个可选参数确定节的名。这个名是任意的,应当设置为一个你认为符合本节目的的描述性的名字。
考虑一个例子。假设希望循环处理一周中的每一天:
daysofweek.tpl文件包含:
这会返回如下结果:
可以使用key属性迭代处理一个关联数据。考虑以下例子:
daysofweek.tpl模板包含:
这会返回:
虽然foreach函数非常有用,但绝对需要花些时间学习另一个功能与之类似的函数――section函数。这个函数功能更强大,我们将在后面介绍。
3.foreachelse函数
foreachelse函数与foreach一起使用,与用于字符串的default标记作用类似,数组为空时foreachelse标记可以生成某个候选结果。以下是一个使用foreachelse的模板示例:
注意,foreachelse不使用结束括号,它嵌入到foreach中,这与elseif嵌入到if函数中很类似。
4.section函数
section函数的操作就像是一个改进的for/foreach语句,它会迭代处理并输出数据数组,但其语法差别很大。这里改进一词是指它与for/foreach结构提供了相同的循环特性,另外还提供了很多附加选项,可以更多地控制循环的执行。这些选项要通过函数参数来支持。下面将通过几个例子来介绍各个可用的选项参数。
有两个参数是必要的,如下所示。
qname。确定节的名。节名可以任意,应当设置为能够描述节的目的的任意名字。
qloop。设置循环迭代的次数。应当设置为与数组变量同名。
还有几个可选参数,如下所示。
qstart。确定迭代开始的索引位置。例如,如果数组包含5个值,而start设置为3,则迭代将从数组的索引3开始。如果给出的是负值,则起始位置由从数组末尾减去该数字来确定。
qstep。确定在数组中移动的步长值。默认情况下,这个值为1。例如,设置step为3将导致迭代在数组索引0、3、6、9等等发生。设置step为负值将导致迭代从数组末尾向前进行。
qmax。确定迭代的最大次数。
qshow。确定是否确实显示此节。可以使用这个参数进行调试(先设置为TRUE),然后在部署时再把这个参数设置为FALSE。
考虑两个示例。第一个示例迭代处理一个简单的索引数组:
titles.tpl模板包含:
这会返回:
在这个有些奇怪的语法中,注意,节名必须像数组中的索引值一样引用。还要注意,$titles变量名有双重职责,它既是循环指示器,也是实际的变量引用。
现在考虑一个使用关联数组的例子:
section2.tpl模板包含:
这会返回:
5.sectionelse函数
sectionelse函数与section一起使用,这与用于字符串的default函数作用类似,数组为空时它生成某个候选输出。使用sectionelse的模板示例如下: