2011.06.14
yna 開発

テンプレートエンジンの話

今から15年位前、インターネットが始まったころ、動的なサイトを作るには、Perlという言語でCGIを作るのが一般的でした。そのころのプログラムは、Perlのプログラムの中にヒアドキュメントを用いてHTMLを強制的に埋め込むのが普通でした。

商品名 単価 個数 小計
りんご 100 5 500
みかん 70 4 280
120 3 360

たとえば、上のような表一つ出すのにも、こんなコードを書いていました。

sub     showHtml($)
{
    my  ($aryRec) = @_;
    my  $tablebody = "";
    for my $rec ( @$aryRec ){
        $tablebody .= << "ENDREC";
      <tr>
        <td align="left">$rec->{name}</th>
        <td align="right">$rec->{unit}</th>
        <td align="right">$rec->{count}</th>
        <td align="right">$rec->{total}</th>
      </tr>
ENDREC
    }

    print << "ENDHTM";
Content-Type: text/html; charset=Shift_JIS

<html>
  <body>
    <table border=1>
      <tr>
        <th width=240>商品名</th>
        <th width=100>単価</th>
        <th width=60>個数</th>
        <th width=100>小計</th>
      </tr>
$tablebody
    </table>
  </body>
</html>
ENDHTM
}
・・・

 HTMLとコードが混在してますし、HTMLとコードの順番もバラバラで、ちょっと何をやっているコードか分かりませんね。
 こういう方法では、ちゃんと書くのは大変ということで、次第によく使われるようになったのが、ASPやPHPなどのHTML埋め込み型の言語です。

<?php
$aryRecord = array(
    array( "name" => "りんご",  "unit" => 100,"count" => 5,"total" => 500 ),
    array( "name" => "みかん",  "unit" => 70,"count" => 4,"total" => 280 ),
    array( "name" => "梨",      "unit" => 120,"count" => 3,"total" => 360 ),
);

?>
<html>
  <body>
    <table border=1>
      <tr>
        <th width=240>商品名</th>
        <th width=100>単価</th>
        <th width=60>個数</th>
        <th width=100>小計</th>
      </tr>
<?php
    foreach( $aryRecord as $rec ){
?>
      <tr>
        <td align="left"><?php print $rec["name"]; ?></th>
        <td align="right"><?php print $rec["unit"]; ?></th>
        <td align="right"><?php print $rec["count"]; ?></th>
        <td align="right"><?php print $rec["total"]; ?></th>
      </tr>
<?php
      }
?>
    </table>
  </body>
</html>

 さっきのPerlで書かれたプログラムよりは分かりやすいですよね。
 さて、単純なHTMLしか作成しなかった頃にはこんな方法でも十分だったのですが、デザイン重視のHTMLが当たり前になり、デザイナーが作るようになると、HTMLとプログラムが分離しないということが問題になるようになってきました。
 ここで出てきたのはテンプレートとプログラムを分離して扱うという考え方です。

 このプログラムは、最も初期のテンプレートのサブルーチンです。
 コメントを入れても70行程度と、最近使われているSmartyのようなテンプレートエンジンに比べると赤ん坊のようなものです。load_templateでセクション記号ごとに分割してテンプレートをロードし、replace_htmlで特定の記号で囲まれたキーワード(ここでは、##~##)を置き換えます。
この程度のサブルーチンでも、だいぶ見通しのよいプログラムを書けるようになりました。

 テンプレートファイルは、こんな感じになります。この程度の埋め込みであれば、デザイナーに渡しても戸惑うことなく作業してくれそうです。

<!--#HEAD-->
<html>
  <body>
    <table border=1>
      <tr>
        <th width=240>商品名</th>
        <th width=100>単価</th>
        <th width=60>個数</th>
        <th width=100>小計</th>
      </tr>
<!--#LOOP-->
      <tr>
        <td align="left">##name##</th>
        <td align="right">##unit##</th>
        <td align="right">##count##</th>
        <td align="right">##total##</th>
      </tr>
<!--#TAIL-->
    </table>
  </body>
</html>

 プログラム側ではこんな感じに使います。
 最初にHEADセクションを表示して、それから、LOOPをデータ個数だけ繰り返して、最後にTAILを表示するようになっています。

sub     showHtml($)
{
my  @aryRecord = (
    { "name" => "りんご",   "unit" => 100,  "count" => 5,   "total" => 500 },
    { "name" => "みかん",   "unit" => 70,   "count" => 4,   "total" => 280 },
    { "name" => "梨",       "unit" => 120,  "count" => 3,   "total" => 360 },
);
    my  (%tmpl, $html, $ary, $rec, %hash);
    # テンプレートを読み込む
    load_template( \%tmpl, "showlist.thtm" ) 
        or die "Fail load template";
    my  @ary = 
    $html = replace_html( \%tmpl, 'HEAD' );
    for $rec ( @aryRecord ){
        $html .= replace_html( \%tmpl, 'LOOP', $rec );
    }
    $html .= replace_html( \%tmpl, 'TAIL' );
    print $html;
}

さて、次回は、もう少し進んだ形のテンプレートエンジンの話をしましょう。
yna

一覧に戻る