Smartyを使うとき、DBからデータを配列で取得し、ループで回してテーブルを作成する、と言う処理が一番多いのではないでしょうか。そんなループ処理の1つとして{section}関数がSmartyにはあります。
Smartyを使うとき、DBからデータを配列で取得し、ループで回してテーブルを作成する、と言う処理が一番多いのではないでしょうか。そんなループ処理の1つとして{section}関数がSmartyにはあります。
{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}
テーブルを表示させる場合、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}