{section}関数でループさせる

Smartyを使うとき、DBからデータを配列で取得し、ループで回してテーブルを作成する、と言う処理が一番多いのではないでしょうか。そんなループ処理の1つとして{section}関数がSmartyにはあります。

{section}関数の形式

{section}関数の形式と各属性は下記のようになります。

{section name=counter loop=$array_data start=2 step=2 max=10}
    {if $smarty.section.counter.first}    {* 最初のループ時にtrueになります *}
	  最初のデータ
    {/if}
    {if $smarty.section.counter.last}     {* 最後のループ時にtrueになります *}
	  最後のデータ
    {/if}
    {$smarty.section.counter.index}       {* 現在のループインデックス Zero Originです。*}
    {$smarty.section.counter.index_prev}  {* 前ループのインデックス値 *}
    {$smarty.section.counter.index_next}  {* 次ループのインデックス値 *}
    {$smarty.section.counter.iteration}   {* 現在のループ回数 1 Originです。*}
    {$smarty.section.counter.rownum}      {* 現在のループ回数 1 Originです。(iterationと同じ) *}
    {$smarty.section.counter.loop}        {* 最後のインデックス値 *}
    {$smarty.section.counter.total}       {* ループした回数 *}
    {$array_data[counter]}                {* 配列の値 *}
{sectionelse}
    データが無いよ。
{/section}	

{section}のloop属性に配列名(例えばloop=$array_data)を、name属性に適当な名前(例えばname=counter)を付けて、{$array_data[counter]}のような形でループするデータにアクセスします。

loopには数字をセットする事もできるので、セットした数字だけループさせる処理も可能です。

{section name=counter loop=10}
10回表示するぞ。<br/>
{/section}	

例えば、プログラム上で、下記のようにアサインされていた場合、各属性の値はこのようになります。

$Smarty->assign('array_data',range('a','z'));

多次元配列のアクセス

多次元配列の場合、配列と連想配列で参照方法が異なるので例をあげておきます。

// 配列をセット
$data1 = array(1000,1001,1002);
$smarty->assign('data1',$data1);  //配列をアサイン

// 多次元配列をセット
$data2 = array(
	       array('a',1000),
	       array('b',1002),
	       array('c',1003),
	       array('d',1004),
	       );
$smarty->assign('data2',$data2);  //多次元配列をアサイン
	  
// 連想配列をセット
$data3 = array(
	       array('id'=>1,'name'=>'foo'),
	       array('id'=>2,'name'=>'bar'),
	       array('id'=>3,'name'=>'hoge'),
	       array('id'=>4,'name'=>'moge')
	       );
$smarty->assign('data3',$data3);  //連想配列をアサイン
	
// 連想配列をセット
$data4 = array(
	       "a" => array('id'=>1,'name'=>'foo'),
	       "b" => array('id'=>2,'name'=>'bar'),
	       "c" => array('id'=>3,'name'=>'hoge'),
	       "d" => array('id'=>4,'name'=>'moge')
	       );
$Smarty->assign('data4',$data4);  //連想配列をアサイン

テンプレート側では、次のように参照します。

<h2>配列data1の出力</h2>
{section name=row loop=$data1}
  data: {$data1[row]}<br />
{/section}
	
<h2>多次元配列data2の出力</h2>
{section name=row loop=$data2}
  {* 多次元配列は$data2[row][0] または $data2[row].0 でアクセスできます。 *}
  data: {$data2[row][0]} {$data2[row].1}<br />
{/section}

<h2>連想配列data3の出力</h2>
{section name=row loop=$data3}
  {* 連想配列は$data3[row].id でアクセスできます。 ($data3[row][id]ではアクセスできません。) *}
  data: {$data3[row].id} {$data3[row].name}<br />
{/section}

<h2>連想配列data4の出力</h2>
{section name=row loop=$data4}
  {* 配列の添字が全て文字列の連想配列は{foreach}関数を使う必要があります。 *}
  data: {$data4[row].id} {$data4[row].name}<br />
{/section}
	  
<h2>データが無い場合</h2>
{section name=row loop=$data5}
  data: {$data5[row].id} {$data5[row].name}<br />
{sectionelse}
  {* $data5が無い場合は {sectionelse}が実行されます。 *}
  データがありません。<br />
{/section}      

sectionの例

テーブルを作ってみる

テーブルを表示させる場合、smartyには{html_table}関数があるのですが、結構癖があるので{section}などでデータをループさせながら、テーブルを作成する方法が一般的かなと思います。

まず、テーブルに表示するデータを用意する必要がありますが、今回はなんちゃって個人情報と言う、「偽個人情報ジェネレータ」のデータを使用して見たいと思います。

でもって、上記のサイトで作成したデータをCVS形式で出力したものがdummy_data.csvです。このファイルをプログラム側で読込み、テンプレート側に渡してテーブルを作成します。

プログラム側

プログラムでは、fgetcsv関数dummy_data.csvを読込み、$data変数に配列で格納します。

if(!$handle = fopen("dummy_data.csv", "r")){
    echo "Cannot open file (dummy_data.csv)";
    exit;
}
// csvファイルの読込み
while (($data[] = fgetcsv($handle, 1000, ",")) !== FALSE);
fclose($handle);

$Smarty = new MySmarty();
$Smarty->assign('title',"テーブル作成");
$Smarty->assign('data',$data);
$Smarty->display('section3.tpl');	

テンプレート側

渡されたデータの最初には、タイトル情報が入っているので、最初のループではテーブルヘッダ部分(<thead>)を作成します。2番目以降は普通のデータなので<tbody>の中にデータを表示します。

<table class="mytable">
  {section name=counter loop=$data}
    {if $smarty.section.counter.first}
    {* 最初のデータはデータタイトルなので、タイトル作成 *}
  <thead>
    <tr>
      {* タイトルデータの配列を sectionでループ *}
      {section name=h_counter loop=$data[counter]}
      <th>{$data[counter][h_counter]}</th>
      {/section}
    </tr>
  </thead>
  <tbody>
    {else}
    {* 二番目以降は普通のデータ *}
    <tr class="{cycle values='add,even'}"> {* cycle を使用して列の色を変化させる *}
      {* データの配列を sectionでループ *}
      {section name=h_counter loop=$data[counter]}
      <td>{$data[counter][h_counter]}</td>
      {/section}
    </tr>
    {/if}
  {/section}
  </tbody>
</table>

テーブルの例

日付ラジオボックスを作ってみる

{section}は、PHPのfor文と同じような使い方も可能なので、これを利用して日付ラジオボックスを作ってみます。

プログラム側

プログラムは、特にやることはないです。

$Smarty = new MySmarty();
$Smarty->assign('title',"日付ラジオボックス作成");
$Smarty->display('section4.tpl');	

テンプレート側

テンプレートでは下記のことをしています。

これ以外に、ラジオボックスの横に表示する日付を{$smarty.section.time.index|jp_date_format:'%Y年%m月%d日(%a)'}として表示しています。

smartyには、幾つかの変数修飾子があり、その中にunixタイムスタンプを指定した形式にフォーマットしてくれるdate_formatがあります。しかし、date_formatは曜日の表示が日本語に対応しておらず、英語表記で表示されてしまいます。

これを日本語表記に対応させたjp_date_formatを作った方がおられたので、これを使用させてもらっています。

{section name=time start=$smarty.now loop=$smarty.now+604800 step=86400}
<label>
  <input type="radio" name="date" value="{$smarty.section.time.index}">
  {$smarty.section.time.index|jp_date_format:'%Y年%m月%d日(%a)'}
</label>
{/section}	

ラジオボックスの例

Last modified: Thu Feb 21 15:06:13 2008 JST