# 快速入門(九):循環和控制輸出
在上一章我們了解了如何把變量輸出到模板中,這一篇我們來進一步了解如何進行模板數據的循環和控制輸出。
注意,本篇的描述僅針對使用內部模板引擎的情況,如果你使用了Smarty或者其他模板引擎,請參考其相關的變量輸出語法。
## 循環輸出
循環輸出主要是使用volist和foreach標簽輸出。
### VOLIST
volist標簽通常用于查詢數據集(select方法)的結果輸出,通常模型的select方法返回的結果是一個二維數組,可以直接使用volist標簽進行輸出。
在控制器中首先對模版賦值:
~~~
$User = M('User');
$list = $User->limit(10)->select();
$this->assign('list',$list);
~~~
在模版定義如下,循環輸出用戶的編號和姓名:
~~~
<volist name="list" id="vo">
{$vo.id}:{$vo.name}<br/>
</volist>
~~~
Volist標簽的`name屬性`表示模板賦值的變量名稱,因此不可隨意在模板文件中改變。`id`表示當前的循環變量,可以隨意指定,但確保不要和name屬性沖突,例如:
~~~
<volist name="list" id="data">
{$data.id}:{$data.name}<br/>
</volist>
~~~
支持輸出查詢結果中的部分數據,例如輸出其中的第5~15條記錄
~~~
<volist name="list" id="vo" offset="5" length='10'>
{$vo.name}
</volist>
~~~
輸出偶數記錄
~~~
<volist name="list" id="vo" mod="2" >
<eq name="mod" value="1">{$vo.name}</eq>
</volist>
~~~
Mod屬性還用于控制一定記錄的換行,例如:
~~~
<volist name="list" id="vo" mod="5" >
{$vo.name}
<eq name="mod" value="4"><br/></eq>
</volist>
~~~
為空的時候輸出提示:
~~~
<volist name="list" id="vo" empty="暫時沒有數據" >
{$vo.id}|{$vo.name}
</volist>
~~~
empty屬性不支持直接傳入html語法,但可以支持變量輸出,例如:
~~~
$this->assign('empty','<span class="empty">沒有數據</span>');
$this->assign('list',$list);
~~~
然后在模板中使用:
~~~
<volist name="list" id="vo" empty="$empty" >
{$vo.id}|{$vo.name}
</volist>
~~~
模板中可以直接使用函數設定數據集,而不需要在控制器中給模板變量賦值傳入數據集變量,如:
~~~
<volist name=":fun('arg')" id="vo">
{$vo.name}
</volist>
~~~
### FOREACH
除了volist標簽之外,還可以使用foreach標簽,foreach標簽類似與volist標簽,只是更加簡單,沒有太多額外的屬性,例如:
~~~
<foreach name="list" item="vo">
{$vo.id}:{$vo.name}
</foreach>
~~~
name表示數據源 item表示循環變量。
foreach標簽還可以輸出一維數組,例如:
~~~
<foreach name="list" item="vo" >
{$key}|{$vo}
</foreach>
~~~
## 條件輸出
條件輸出最常用的包括switch、if以及eq等比較標簽。
### SWITCH
用法:
~~~
<switch name="變量" >
<case value="值1" break="0或1">輸出內容1</case>
<case value="值2">輸出內容2</case>
<default />默認情況
</switch>
~~~
使用方法如下:
~~~
<switch name="User.level">
<case value="1">value1</case>
<case value="2">value2</case>
<default />default
</switch>
~~~
其中name屬性可以使用函數以及系統變量,例如:
~~~
<switch name="Think.get.userId|abs">
<case value="1">admin</case>
<default />default
</switch>
~~~
對于case的value屬性可以支持多個條件的判斷,使用”|”進行分割,例如:
~~~
<switch name="Think.get.type">
<case value="gif|png|jpg">圖像格式</case>
<default />其他格式
</switch>
~~~
表示如果$_GET["type"] 是gif、png或者jpg的話,就判斷為圖像格式。
Case標簽還有一個break屬性,表示是否需要break,默認是會自動添加break,如果不要break,可以使用:
~~~
<switch name="Think.get.userId|abs">
<case value="1" break="0">admin</case>
<case value="2">admin</case>
<default />default
</switch>
~~~
也可以對case的value屬性使用變量,例如:
~~~
<switch name="User.userId">
<case value="$adminId">admin</case>
<case value="$memberId">member</case>
<default />default
</switch>
~~~
### 比較標簽
比較標簽用于簡單的變量比較,復雜的判斷條件可以用if標簽替換,比較標簽是一組標簽的集合,基本上用法都一致,如下:
~~~
<比較標簽 name="變量" value="值">
內容
</比較標簽>
~~~
系統支持的比較標簽以及所表示的含義分別是:
|標簽|含義|
|-----------|-----------------|
|eq或者 equal| 等于 |
|neq 或者notequal| 不等于 |
|gt |大于 |
|egt |大于等于 |
|lt |小于 |
|elt |小于等于 |
|heq |恒等于 |
|nheq |不恒等于 |
他們的用法基本是一致的,區別在于判斷的條件不同,并且所有的比較標簽都可以和else標簽一起使用。
例如,要求name變量的值等于value就輸出,可以使用:
~~~
<eq name="name" value="value">value</eq>
~~~
或者
~~~
<equal name="name" value="value">value</equal>
~~~
也可以支持和else標簽混合使用:
~~~
<eq name="name" value="value">
相等
<else/>
不相等
</eq>
~~~
當 name變量的值大于5就輸出
~~~
<gt name="name" value="5">value</gt>
~~~
當name變量的值不小于5就輸出
~~~
<egt name="name" value="5">value</egt>
~~~
比較標簽中的變量可以支持對象的屬性或者數組,甚至可以是系統變量,例如:
當vo對象的屬性(或者數組,或者自動判斷)等于5就輸出
~~~
<eq name="vo.name" value="5">
{$vo.name}
</eq>
~~~
當vo對象的屬性等于5就輸出
~~~
<eq name="vo:name" value="5">
{$vo.name}
</eq>
~~~
當$vo['name']等于5就輸出
~~~
<eq name="vo['name']" value="5">
{$vo.name}
</eq>
~~~
而且還可以支持對變量使用函數
當vo對象的屬性值的字符串長度等于5就輸出
~~~
<eq name="vo:name|strlen" value="5">{$vo.name}</eq>
~~~
變量名可以支持系統變量的方式,例如:
~~~
<eq name="Think.get.name" value="value">相等<else/>不相等</eq>
~~~
通常比較標簽的值是一個字符串或者數字,如果需要使用變量,只需要在前面添加“$”標志:
當vo對象的屬性等于$a就輸出
~~~
<eq name="vo:name" value="$a">{$vo.name}</eq>
~~~
## 范圍判斷標簽
范圍判斷標簽包括`in`、`notin`、`between`和`notbetween`四個標簽,都用于判斷變量是否中某個范圍。
### IN和NOTIN
用法:
假設我們中控制器中給id賦值為1:
~~~
$id = 1;
$this->assign('id',$id);
~~~
我們可以使用in標簽來判斷模板變量是否在某個范圍內,例如:
~~~
<in name="id" value="1,2,3">
id在范圍內
</in>
~~~
最后會輸出:`id在范圍內`。
如果判斷不在某個范圍內,可以使用:
~~~
<notin name="id" value="1,2,3">
id不在范圍內
</notin>
~~~
可以把上面兩個標簽合并成為:
~~~
<in name="id" value="1,2,3">
id在范圍內
<else/>
id不在范圍內
</in>
~~~
name屬性還可以支持直接判斷系統變量,例如:
~~~
<in name="Think.get.id" value="1,2,3">
$_GET['id'] 在范圍內
</in>
~~~
value屬性也可以使用變量,例如:
~~~
<in name="id" value="$range">
id在范圍內
</in>
~~~
$range變量可以是數組,也可以是以逗號分隔的字符串。
### BETWEEN 和 NOTBETWEEN
可以使用between標簽來判斷變量是否在某個區間范圍內,可以使用:
~~~
<between name="id" value="1,10">
輸出內容1
</between>
~~~
同樣,可以使用notbetween標簽來判斷變量不在某個范圍內:
~~~
<notbetween name="id" value="1,10">
輸出內容2
</notbetween>
~~~
也可以使用else標簽把兩個用法合并,例如:
~~~
<between name="id" value="1,10">
輸出內容1
<else/>
輸出內容2
</between>
~~~
當使用between標簽的時候,value只需要一個區間范圍,也就是只支持兩個值,后面的值無效,例如
~~~
<between name="id" value="1,3,10">
輸出內容1
</between>
~~~
實際判斷的范圍區間是`1~3`,而不是`1~10`,也可以支持字符串判斷,例如:
~~~
<between name="id" value="A,Z">
輸出內容1
</between>
~~~
name屬性可以直接使用系統變量,例如:
~~~
<between name="Think.post.id" value="1,5">
輸出內容1
</between>
~~~
value屬性也可以使用變量,例如:
~~~
<between name="id" value="$range">
輸出內容1
</between>
~~~
## 賦值判斷標簽
可以使用present、empty等標簽進行賦值判斷輸出。
present標簽用于判斷某個變量是否已經定義,用法:
~~~
<present name="name">
name已經賦值
<else />
name還沒有賦值
</present>
~~~
name屬性可以直接使用系統變量,例如:
~~~
<present name="Think.get.name">
$_GET['name']已經賦值
</present>
~~~
empty標簽用于判斷某個變量是否為空,用法:
<empty name="name">
name為空
<else />
name不為空
</empty>
name屬性可以直接使用系統變量,例如:
~~~
<empty name="Think.get.name">
$_GET['name']為空值
</empty>
~~~
DEFINED標簽用于判斷某個常量是否有定義,用法如下:
~~~
<defined name="NAME">
NAME常量已經定義
<else />
NAME常量未定義
</defined>
~~~
## 原生代碼
Php代碼可以和標簽在模板文件中混合使用,可以在模板文件里面書寫任意的PHP語句代碼 ,包括下面兩種方式:
### 第一種:使用php標簽
例如:
~~~
<php>echo 'Hello,world!';</php>
~~~
我們建議需要使用PHP代碼的時候盡量采用php標簽,因為原生的PHP語法可能會被配置禁用而導致解析錯誤。
### 第二種:使用原生php代碼
~~~
<?php echo 'Hello,world!'; ?>
~~~
## 總結
本章我們講述了模板中進行循環和控制輸出,下一篇我們還會講述如何使用公共模板和布局模板來簡化模板文件的定義。