HTML::Template.pmHTMLに特化したテンプレート
HTMLに特化したというよりは、テンプレート内の置き換え記述がタグ風なテンプレート変換モジュールです。
HTMLの内容の一部を置き換えるためではなく、置き換える箇所がHTMLタグっぽい記述であるということ。置き換える対象となるテキストはHTMLでなくてもいいですし。
HTMLタグのように置き換え部分を記述するため、そのテンプレートをBrowserで表示したとき、 タグ解釈や「”」タブルクォートの解釈が入れ子になったりしてきれいに表示できないという 欠点もあります。
テンプレート変換ではText::Templateの方を使う人も多いと思います。
自分が好んでHTML::Templateを使う理由は、ループ構造を表現するのに適しているからです。 特に、HTMLの表示、ブラウザ表示するようなプログラムは、単票の表示形式と、定型のパターンで繰り返す表形式の2とおりでほとんど表現できます。
ループ構造の入れ子もできるし、複雑な画面でなければ、プログラムからHTMLタグの表現を 排除することも可能です。
ページデザインとプログラムの切り分けの境界にこのHTML::Templateを置くことになります。
プログラムからHTMLの記述を排除することができます。 また、HTML::Templateの記述には条件分岐(<TMPL_IF>など)も用意されています。
Templateの方にプログラム要素を追い出してしまうこともできてしまいます。 あまりやりすぎると、プログラムでやるべきことも、テンプレートの表記でやってしまう ようになり、結局、どちらで何をやっているのかが見えづらくなってしまいます。 「こういうときは、どちらでどのように対処する」といった、ルールを予め作っておくと 混乱しにくくなります。
テンプレートファイルを使ってテンプレートオブジェクトを生成する典型です。
use HTML::Template;
my $tmpl = HTML::Template->new(
die_on_bad_params => 0,
filename => './templates/sample.htm'
);
die_on_bad_paramsはdefalutでonになってます。
テンプレート変換する際、設定されていない変数(テンプレート変数)を指定するとエラーになる など、パラメータに関するエラーがありますが、die_on_bad_params=0にすると無視(エラー にならない)します。
厳密に処理を作成したいのであれば有効にしたいオプションですが、無効にした方が 便利なので、私の場合は0を設定して使っています。
filenameはテンプレートとなるファイルのファイル名を渡します。 それ以外にファイルでなく、テキスト変数を渡し、その内容を変換する方法などがあります。 Perl/Yaino/RSSを参照。
参照と設定のできる変換パラメータのアクセサです。 通常は設定のみの使用になるでしょう。
テンプレートをパラメータで変換した結果を返します。
テンプレートのファイル名は自由に付けることができます。自分の場合は、HTMLファイルは .htmlを、テンプレートには.htmを拡張子(UNIX系に拡張子という用語があったか?)を付けて ます。拡張子を付けておくと手間なくブラウザでプレビューできるし。
データ表示の一覧を作る簡単なプログラムを作ってみます。
サンプル<br>
データ一覧<br>
yainoさんのデータ<br>
名前 -- 内容<br>
101 -- abc<br>
102 -- def<br>
yaino,101,abc,102,defの部分が可変で、データの個数も可変である場合のサンプルです。
テンプレートサンプル sample1.htm
<html>
<head><title>HTML::Template sample1</title></head>
<body>
<h2>サンプル</h2>
<h3>データ一覧</h3>
<TMPL_VAR name=user_name>さんのデータ<br>
名前 -- 内容<br>
<TMPL_IF name=arr_data_num>
<TMPL_LOOP name=arr_data>
<TMPL_VAR name=data_code> -- <TMPL_VAR name=data_name><br>
</TMPL_LOOP>
<TMPL_ELSE>
データはありません
</TMPL_IF>
</body>
</html>
これまた自分の場合ですが、HTMLとして出力されるタグのところは小文字で、HTML::Template の文法のところのタグは大文字で書きます。 HTMLの規格はタグを小文字に書くように移行しているようです。 また、パラメータは"ダブルクォートで囲まないで書きます。 HTMLのタグの中のパラメータにテンプレート変換したい文字を入れる場合もありますが、 そのときの記述で下記のような場合、
<form method="POST" action="<TMPL_VAR name=cgi_name>">
value:<input type="text" name="inp_data" value="">
<input type="submit" value="OK">
</form>
HTMLとして出力されるパラメータは"ダブルクォートで囲みますが、 HTML::Templateのパラメータはダブルクォートで囲まないようにしてます。 ダブルクォートがネストして(入れ子になって)しまうので、ブラウザでプレビューしたときに 表示が乱れます。HTML::Templateのテンプレートをプレビューしてもあまり意味があるか 疑問でもありますが。
sample1.htmではTMPL_VAR,TMPL_LOOP,TMPL_IFを使ってみました。他に、TMPL_INCLUDEなんかも有用です。(メニューを別テンプレートにしたりして)
パラメータの'name='を省略できるような記述をどこかで 見た記憶があるのですが、(省略した方がシンプルに書けますね。)しっかり記述してみました。
HTML::Templateのparam()メソッドで定義されたハッシュの名前(key)をnameパラメータで 指定します。定義した値(文字列)に変換されます。
値は<TMPL_VAR name=val>です<br>
$tmpl->param(val=>35);
値は35です<br>
TMPL_LOOPから/TMPL_LOOPまでの間が、[param_key_name]で指定されたハッシュへの 参照の配列の先頭から順番にハッシュが展開されます。一番単純な、ハッシュにkey:valueの ペアが1個だけの場合を書くと、
<TMPL_LOOP name=arr>
val:<TMPL_VAR name=val><br>
</TMPL_LOOP>
@arr = [ {val=>'a1'},{val=>'a2'},{val=>'a3'} ];
$tmpl->param(arr=>\@arr);
この構造であるため、DBIのハッシュの参照配列でI/Oする際、とても便利です。そのうち書きます。
val:a1<br>
val:a2<br>
val:a3<br>
この場合、配列の数3で繰り返されます。それぞれの1ハッシュのkey='val'に対応する 値が展開されます。
表示の制御を値が真(True,!=0)かそれ以外か(False,==0)で分岐します。
<TMPL_IF name=flg>
yesです<br>
<TMPL_ELSE>
noです<br>
</TMPL_IF>
$tmpl->param(flg=>1);
yesです<br>
分岐処理などはプログラムでやるべきです。テンプレートでやるべきではないと私は思います。 ただし、業務エラーとしたくないような0件エラーなどの警告は、テンプレートで分岐した ほうが運用で有利かと思います。0件のとき、TABLE組したデータを表示できないですから、 エラー画面を一緒にテンプレートに入れてしまった方がいいでしょう。
当然、深刻なエラーなどは別画面を表示する仕組みを作るべきです。
HTMLのバーツを埋め込むことができます。埋め込み側のHTMLにもHTML::Tmplateの文法が 使えます。
それでは、sample1.htmに対応するプログラムを書きます。
sample1.pl
use HTML::Template;
my $tmpl = HTML::Template->new(
die_on_bad_params => 0,
filename => 'sample1.htm'
);
my @user_data = [
{data_code=>101,data_name=>'abc'},
{data_code=>102,data_name=>'def'},
};
#------------------
# パラメータの設定
#------------------
$tmpl->param(user_name =>'yaino');
$tmpl->param(arr_data =>\@user_data);
$tmpl->param(arr_data_num=>scalar(@user_data));
#-----------------
# 出力
#-----------------
print "Content-Type: text/html\n\n";
print $tmpl->output();
パラメータの設定は当然、一度に設定する事もできます。
$tmpl->param(
user_name => 'yaino',
arr_data => \@user_data,
arr_data_num => scalar(@user_data)
);
プログラム段階ごとに処理をして設定する場合なんかは小分けして
$value1= ... # value1を設定する処理をする
$tmpl->param(key1=>$value1);
$value2= ... #value2を設定する処理をする
$tmpl->param(key2=>$value2, 他のkeyなども設定したり);
なんて感じになるし。
あとは、出力をTABLEタグを使ったりしたかったらテンプレートに手を加えるだけです。 応用してみてください。