{foreach}関数(ループ制御)

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

{foreach}関数の形式

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

{foreach name=counter item=data key=array_key from=$array_data}
    {if $smarty.foreach.counter.first}    {* 最初のループ時にtrueになります *}
	  最初のデータ
    {/if}
    {if $smarty.foreach.counter.last}     {* 最後のループ時にtrueになります *}
	  最後のデータ
    {/if}
    {$smarty.foreach.counter.iteration}   {* 現在のループ回数 1 Originです。*}
    {$smarty.foreach.counter.total}       {* ループした回数 *}
    {$data}                               {* 配列の値 *}
    {$array_key}                          {* 配列のkey *}
{foreachelse}
    データが無いよ。
{/foreach}	

{foreach}のfrom属性に配列名(例えばfrom=$array_data)を、item属性に適当な名前(例えばitem=data)を付けて、{$data}のような形でループするデータにアクセスします。また、連想配列のキーが必要な場合は、key属性に名前(例えばitem=array_key)を付けて{$array_key}の形で、現在のキーを取得できます。

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

for($i='A';$i<'Z';$i++){
    $array_data[$i]=strtolower($i);
}
$Smarty->assign('array_data',$array_data);

多次元配列のアクセス

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

// 配列をセット
$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>
{foreach name=counter item=data key=array_key from=$data1}
  {* {foreach}は配列でも連想配列でも扱えます。 *}
  data: key={$array_key} data={$data}<br />
{/foreach}
	
<h2>多次元配列data2の出力</h2>
{foreach name=counter item=data key=array_key from=$data2}
  {* 多次元配列は$data[0] または $data.0 でアクセスできます。 *}
  data: key={$array_key} data[0]={$data[0]} data[1]={$data.1}<br />
{/foreach}

<h2>連想配列data3の出力</h2>
{foreach name=counter item=data key=array_key from=$data3}
  {* 添字が文字列の場合は$data.id でアクセスできます。 ($data[id]ではアクセスできません。) *}
  data: key={$array_key} id={$data.id} name={$data.name}<br />
{/foreach}

<h2>連想配列data4の出力</h2>
{foreach name=counter item=data key=array_key from=$data4}
  data: key={$array_key} id={$data.id} name={$data.name}<br />
{/foreach}
	  
<h2>データが無い場合</h2>
{foreach name=counter item=data key=array_key from=$data5}
  data: key={$array_key} {$data.id} {$data.name}<br />
{foreachelse}
  {* $data5が無い場合は {foreachelse}が実行されます。 *}
  データがありません。<br />
{/foreach}      

foreachの例

{foreach}を使ってテーブルを作ってみる

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

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

でもって、上記のサイトで作成したデータを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">
  {foreach name=counter item=users from=$data}
    {if $smarty.section.counter.first}
    {* 最初のデータはデータタイトルなので、タイトル作成 *}
  <thead>
    <tr>
      {* タイトルデータの配列を foreachでループ *}
      {foreach item=title_data from=$users}
      <th>{$title_data}</th>
      {/foreach}
    </tr>
  </thead>
  <tbody>
    {else}
    {* 二番目以降は普通のデータ *}
    <tr class="{cycle values='add,even'}"> {* cycle を使用して列の色を変化させる *}
      {* データの配列を foreachでループ *}
      {foreach item=user_data from=$users}
      <td>{$user_data}</td>
      {/foreach}
    </tr>
    {/if}
  {/foreach}
  </tbody>
</table>

テーブルの例

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