by Hippo2000(2000/8/23、
2001/6/14)
HTML::Templateモジュールは名前の通りHTMLのテンプレートを実現し、デザインとプログラムを分けることを目的としたモジュールです。
作者はSam Tregarさんです。メールで許可をいただきました。
内容等が間違っていたら修正します。ご連絡ください。
2001/6/14
yahoo-otuzuki さんからの指摘を受けた部分について(やっと)修正しました。ありがとうございます。
もう少しちゃんとしなくちゃ。
HTML::Template - CGIスクリプトからHTMLテンプレートを使うためのPerlモジュール
最初にテンプレートを作ります - これは<TMPL_VAR>のようにとても簡単な、2、3の特殊なタグが入った普通のHTMLファイルです。
例えば、 test.tmpl:
<HTML> <HEAD><TITLE>Test Template</TITLE> <BODY> My Home Directory is <TMPL_VAR NAME=HOME> <P> My Path is set to <TMPL_VAR NAME=PATH> </BODY> </HTML>
そして小さなCGIプログラムを作ります:
use HTML::Template;
# HTMLテンプレートをオープン my $template = HTML::Template->new(filename => 'test.tmpl');
# パラメータを埋める
$template->param(
HOME => $ENV{HOME},
PATH => $ENV{PATH},
);
# 必須のContent-Typeを送信 print "Content-Type: text/html\n\n";
# テンプレートを出力 print $template->output;
これですべてがうまくいっていれば、ブラウザでそのCGIにいくと、以下のようなものが表示されます:
My Home Directory is /home/some/directory My Path is set to /bin;/usr/bin
このモジュールはHTMLテンプレートを使うことを簡単に、自然にしようとします。これは標準のHTMLをいくつかの新しいHTML風のタグ - <TMPL_VAR>, <TMPL_LOOP>, <TMPL_INCLUDE>, <TMPL_IF> そして <TMPL_ELSE>で拡張します。HTMLとこれらの新しいタグで書かれたファイルはテンプレートと呼ばれます。これは通常スクリプトとは別に保存されます - もしかしたら他の誰かによって作成されることさえあるかもしれません!このモジュールを使って、変数のための値を埋めたり、テンプレートで宣言されたループや分岐をおこないます。これによりPerlスクリプトで作成されるデータからデザイン- HTML-を分けることが出来ます。
このモジュールはGPLの元でライセンスされます。詳細についてはライセンス(LICENSE)・セクションをご覧下さい。
HTMLテンプレートを行っているパッケージがたくさんあることは事実です。HTML::EmbperlのようにHTMLに自由にPerlを混ぜることを許すものもあります。さらに一方では自家製の変数置換による解決法もあります。このモジュールが、それら2つの間に居場所を見つけられることを望んでいます。
このモジュールのフルのHTML::Embperlのような解決法への1つの有利な点は、、重要な分割−デザインとプログラミング−を強制することです。プログラマには簡単な変数とループをHTMLで使うことに限定し、テンプレートはデザイナやその他のperlを知らない人たちからもアクセスできるようになっています。HTMLのような文法を使っているので、他のものと比べてそのフォーマットを非常に理解しやくなっています。似ていることから、将来的に既存のHTMLエディタ/アナライザがHTML::Templateをサポートするように拡張しやすくなっています。
自家製のタグ置換法に対する有利な点はループをサポートしていることです。私は仕事の中で、HTMLでテーブルを作成するためによく呼び出しています。HTMLそのものはループを表すことが出来ないので、簡単に割り切りすぎたHTMLを使うと大量のHTMLが入てしまいます。HTMLにループ・ステートメントを導入するとこの状況をとても簡単にします。デザイナは1つの行をレイアウトし、プログラマは必要に合わせて何回も埋めることが出来ます−それらはすべてパラメータ名について合意しておく必要があります。
なにより、私がこのモジュールについて最もよいことだと思っていることは、それは1つのことしかしませんし、それを速く、注意深く行います。それはPerlやHTMLを置き換えようとはしません。相互への影響をちょっとだけ増やすだけです。そしてそれはとても速いのです。
注意:こられのタグがHTMLのように見えても、それらはいくつかの点で異なっています。まず全部が1行に収まっていなければなりません。2番目に"ルール破り"が認められています。以下のように:
<IMG SRC="<TMPL_VAR NAME=IMAGE_SRC>">
これは本当は適切なHTMLではなりません。しかしこれは完璧に正しい使い方ですし、予定通りに機能します。
タグでの"NAME="はオプションです、しかし拡張性の点から私はそれを使う事を推奨します。例えば - "<TMPL_LOOP LOOP_NAME>" は受け入れられます。
適切なHTMLへに熱心で、テンプレートがHTML文法に適切であるように従わせたいのであれば、HTMLコメントの形式のなかにテンプレートを入力することが出来ます。これは、HTML::Template処理の前にテンプレートのHTML文法が正しいかどうかをチェックしたいHTML作者やDTD-savvy編集ツールを使っている人には便利でしょう。
<!-- TMPL_VAR NAME=PARAM1 -->
劇的な帯域の節約を実現するために、このドキュメントの残り全てで標準(コメントでない)タグが使われます。
<TMPL_VAR> タグはとても簡単です。テンプレートの中の各<TMPL_VAR>タグのために、$template->param(PARAMETER_NAME => "VALUE")を呼びます。テンプレートが出力されるとき<TMPL_VAR> は指定されたVALUEの文字列で置きかえられます。パラメータに値を設定しなければ、出力の際に飛ばされます。
オプションで、出力から戻される前に値がHTML-エスケープしたいことを示すために、タグの中で"ESCAPE=HTML"オプションを使うことが出来ます(昔のESCAPE=1という書き方もまだサポートされています)。つまり ", <, >, そして & といった文字は、", <, > そして& にそれぞれ変換されます。それらの文字がトラブルを起こしかねない場所でTMPL_VARを使いたいときに便利です。
例:
もし'sam"my'のような値でparam()を呼び出すと、ダブルクオートについてのHTMLの考え方のせいで厄介なことになります。
<INPUT NAME=param TYPE=TEXT VALUE="<TMPL_VAR NAME="param">">
対して以下のようにESCAPE=HTMLを使うと:
<INPUT NAME=param TYPE=TEXT VALUE="<TMPL_VAR ESCAPE=HTML NAME="param">">
paramに渡された値に関わらず、欲しいものを手に入れることが出来ます。ESCAPE="HTML", ESCAPE='HTML' そしてESCAPE='1'とも書けます。HTMLを0で置換すると、エスケープをオフとし、それはデフォルトです。
"ESCAPE=URL" オプションもあります。これはURLに適したVARに使うことが出来ます。それは' 'を+に、'/'を'%2F'に置きかえるといった、URLエスケープをおこないます。
<TMPL_LOOP> タグはちょっとだけ複雑です。<TMPL_LOOP> タグはテキストのセクションを区切り、名前をつけることを可能とします。<TMP_LOOP>の内側に<TMPL_VAR>を置きます。そしてパラメータに代入する(ハッシュ・リファレンス)のparam()にリスト(配列リファレンス)を渡します。ループはこのリストの間、繰り返され、渡す度にテキスト・ブロックからの出力を作成します。設定されないパラメータは飛ばされます。以下に例を示します:
テンプレート:
<TMPL_LOOP NAME=EMPLOYEE_INFO>
Name: <TMPL_VAR NAME=NAME> <P>
Job: <TMPL_VAR NAME=JOB> <P>
<P>
</TMPL_LOOP>
スクリプト:
$template->param(EMPLOYEE_INFO => [
{ name => 'Sam', job => 'programmer' },
{ name => 'Steve', job => 'soda jerk' },
]
);
print $template->output();
出力:
Name: Sam <P> Job: programmer <P> <P> Name: Steve <P> Job: soda jerk <P> <P>
上記にあるように<TMPL_LOOP>は変数代入のリストを取り、出力を作成するループ本体を繰り返します。
しばしば、<TMPL_LOOP>の内容をプログラム的に作成したいことでしょう。以下にそれをどのように行うかの例を示します(他にもいろんな方法が可能です!):
# ループに渡す2つのデータ配列 my @words = qw(I Am Cool); my @numbers = qw(1 2 3);
my @loop_data = (); # ループを保持する配列の初期化
while (@words and @numbers) {
my %row_data; # 行データのための新しいハッシュを取得
# 行を埋める
$row_data{WORD} = shift @words;
$row_data{NUMBER} = shift @numbers;
# 必須のステップ - この行のリファレンスをループに入れる!
push(@loop_data, \%row_data);
}
# 最後にループのデータをloop paramに代入する、再びリファレンスで: $template->param(THIS_LOOP => \@loop_data);
上記の例は以下のようなテンプレートで機能します:
<TMPL_LOOP NAME="THIS_LOOP">
Word: <TMPL_VAR NAME="WORD"><BR>
Number: <TMPL_VAR NAME="NUMBER"><P>
</TMPL_LOOP>
それは以下のような出力を作成します:
Word: I Number: 1
Word: Am Number: 2
Word: Cool Number: 3
<TMPL_LOOP>の中の<TMPL_LOOP>は良好で、期待しているように機能します。param()呼び出しのための文法が悩ましているのであれば、1つのネストしたループでのparam呼び出しの例を以下に示します:
$template->param('ROW',[
{ name => 'Bobby',
nicknames => [
{ name => 'the big bad wolf' },
{ name => 'He-Man' },
],
},
],
);
基本的に、各 <TMPL_LOOP>は1つの配列リファレンスを取得します。配列の内側にはハッシュ・リファレンスをいくつでも入れることが出来ます。これらのハッシュにはループ・テンプレートに1つずつ渡す名前=>値の組が入っています。<TMPL_LOOP>の内側では、<TMPL_LOOP>から利用できる変数だけが入ります。外側のブロックの変数はテンプレート・ループの中では見えません。コンピュータ・サイエンス的にいえば、<TMPL_LOOP>はperlサブルーチンのように新しいスコープを導入したのです。変数をグローバルにしたければ、下記で説明するnewへ'global_vars'を使うことが出来ます。
このタグは現在のテンプレートのタグのある場所に直接テンプレートを入れます。入れられるテンプレートの内容は、その内容がマスター・テンプレートに物理的に入れられているのとまったく同じように使われます。
ファイルはフル・パス- '/'から始まる-で指定することが出来ます。もしフル・パスでなければ、囲まれたファイルへのパスが最初に試されます。その後、もしあれば環境変数HTML_TEMPLAGE_ROOTでのパスが試されます。次にnew()の"path "オプションが試されます。最後にファイル名が直接open()に渡されます。HTML_TEMPLATE_ROOTとnew()への"path"オプションについての詳細は下記をご覧下さい。
無限に再帰するインクルードを避けるため、深さは10レベルに制限されています。この制限は"max_includes"オプションで変えることが出来ます。"max_includes"オプションの詳細については、下記をご覧下さい。
<TMPL_IF>タグは与えられたパラメータ名の値に基づいて、テンプレートのブロックを入れるか入れないかを可能にします。与えられたパラメータの値がPerlでのtrue-'1'のような-であれば、ブロックは出力に入れられます。未定義であるか、falseの値-'0'のような-であれば、飛ばされます。パラメータはTMPL_VARと同じ方法で指定されます。
例のテンプレート:
<TMPL_IF NAME="BOOL">
Some text that only gets displayed if BOOL is true!
</TMPL_IF>
そこで$template->param(BOOL => 1)を呼び出すと、上記のブロックが出力に入ります。
<TMPL_IF> </TMPL_IF> ブロックは正しいHTML::Template構造であれば− VAR、LOOPそして他のIF/ELSEブロック−どこにでもいれることができます。しかし<TMPL_IF>と<TMPL_LOOP>が交差するのは正しくないことに注意してください。
うまくいきません:
<TMPL_IF BOOL>
<TMPL_LOOP SOME_LOOP>
</TMPL_IF>
</TMPL_LOOP>
もしTMPL_LOOPの名前がTMPL_IFで使われていれば、もしLOOPが1つでも行を持っていれば、IFブロックは出力します。例えば:
<TMPL_IF LOOP_ONE>
This will output if the loop is not empty.
</TMPL_IF>
<TMPL_LOOP LOOP_ONE>
....
</TMPL_LOOP>
警告:HTML::Templateの大きな利点はPerlとHTMLを分けることです。もしTMPL_IFのあるところでたくさんのケースを導入し、それがPerlのif()に対応しているのであれば、2つの同期を保持するためのメンテナンス上の問題をおこすでしょう。Perlのコードでのif()に対応することを要求せずにそうできるときにのみ、TMPL_IFを実際に利用するように提案します。
TMPL_ELSEを使うことによりTEMPL_IFブロックの代りのブロックを入れることが出来ます。注意:ブロックを終わらせるのは、まだ</TMPL_IF>であって</TMPL_ELSE>ではありません!
例:
<TMPL_IF BOOL>
Some text that is included only if BOOL is true
<TMPL_ELSE>
Some text that is included only if BOOL is false
</TMPL_IF>
このタグは<TMPL_IF>の反対です。CONTROL_PARAMETERがfalseに設定されているか未定義であるとブロックが出力されます。<TMPL_ELSE>を<TMPL_IF>とまったく同じように<TMPL_UNLESS>と一緒に使うことも出来ます。
例:
<TMPL_UNLESS BOOL>
Some text that is output only if BOOL is FALSE.
<TMPL_ELSE>
Some text that is output only if BOOL is TRUE.
</TMPL_UNLESS>
TMPL_UNLESSでTMPL_LOOPの名前が使われていれば、UNLESSブロックはループに行がなければ出力されます。
<TMPL_UNLESS LOOP_ONE>
This will output if the loop is empty.
</TMPL_UNLESS>
<TMPL_LOOP LOOP_ONE>
....
</TMPL_LOOP>
new()新しいTemplateオブジェクトを作るにはnew()を呼び出します:
my $template = HTML::Template->new( filename => 'file.tmpl',
option => 'value'
);
テンプレート・テキストにどのようにアクセスするかを指定する、少なくとも1つの名前=>値の組を指定してnew()を呼び出さなければなりません。"filename=>'file.tmpl'"を使って、テンプレートとしてオープンされるファイル名を指定することができます。代りに以下のようにすることもできます:
my $t = HTML::Template->new( scalarref => $ref_to_template_text,
option => 'value'
);
そして
my $t = HTML::Template->new( arrayref => $ref_to_array_of_lines ,
option => 'value'
);
これらはメモリ上の資源からテンプレートを初期化します。ほとんどの場合、filenameパラメータを使いたいでしょう。もしテンプレート・ファイルからの読み込みのすべてのディスク・アクセスについて心配であれば、mod_perlと以下に説明するcacheオプションを使ってください。
お好みであれば、3つのnew()呼び出しメソッドは以下のようにもアクセスされます:
my $t = HTML::Template->new_file('file.tmpl', option => 'value');
my $t = HTML::Template->new_scalar_ref($ref_to_template_text,
option => 'value');
my $t = HTML::Template->new_array_ref($ref_to_array_of_lines,
option => 'value');
そして最後のオプションとして、以下のようにも呼び出すことが出来ます:
my $t = HTML::Template->new(type => 'filename',
source => 'file.tmpl');
これはソースタイプの3つ全てに機能します。
環境変数 HTML_TEMPLATE_ROOT が設定され、filenameが/で始まらなければ、パスは$HTML_TEMPLATE_ROOTからの相対(パス)でしょう。例えば−環境変数 HTML_TEMPLATE_ROOTが"/home/sam"に設定され、HTML::Template->new()をファイル名を"sam.tmpl"に設定して呼び出すと、HTML::Templateはテンプレート・ファイルにアクセスするために"/home/sam/sam.tmpl"をオープンしようとします。またnew()への"path"オプションで検索パスに影響を与えることも出来ます−詳細な情報については以下をご覧下さい。
Templarteオブジェクトの動きをnewで変更することが出来ます。これらのオプションが利用できます:
<TMPL_HUH NAME=ZUH>
は通常エラーになりますが、strict=>0でnewを呼び出すと、HTML::Templateはそれを無視します。デフォルトは1です。
これは主にApache/mod_perlのように永続する環境でのみ使われます。各リクエストの後にスクリプトがメモリからアンロードされるので、通常のCGI環境ではまったく利点はありません。通常のCGIのために機能するキャッシュについては、以下の'shared_cache'オプションをご覧下さい。
異なるnew()パラメータ設定はキャッシュのリフレッシュを起しません、テンプレートの変更時刻での変更だけがキャッシュ・リフレッシュを起します。ほとんどの使い方ではこれはうまくいきます。私が簡単にテストしたところ、キャッシュを使うと、mod_perlの下で90%のパフォーマンスの上昇がありました。cacheのデフォルトは0です。
これにより複数のサーバ環境でのメモリ消費が大きく減らされます。例えば、私達のシステムの1つでは、テンプレート・キャッシュに4MBを使い、25個のhttpdプロセスを維持しています- その結果shared_cacheはほぼ100MBも節約しています。もちろんスピードは通常のキャッシュで期待する程度からは少し落ちます。もう1つの通常のキャッシュとshared_casheとの違いは、shared_cacheはCGI環境で機能しますが、通常のキャッシュはApache/mod_perlのような永続する環境でのみ有効です。
デフォルトではHTML::TemplateはIPCキー'TMPL'を共有ルートセグメント(16進数で0x4c504d54)として使います、しかしれこれは、new()の'ipc_key'パラメータに他の4文字または整数値のキーを設定することにより変更することがきます。
共有メモリキャッシュに影響を与えるために使うことが出来る他のオプションはIPC::SharedCacheオプションに対応します - ipc_mode, ipc_segment_size そして ipc_max_sizeです。これらがどのように機能するかは、IPC::SharedCacheをご覧下さい。ほとんどの場合、それらをデフォルトから変更する必要はありません。
HTML::Templateで使われる共有メモリキャッシュシステムについての情報はIPC::SharedCacheをご覧下さい。
注意:このオプションをshared_cacheと組み合わせると、共有メモリに古いテンプレートが永遠にたまってしまうかもしれません!
my $query = new CGI;
my $template = HTML::Template->new(filename => 'template.tmpl',
associate => $query);
そして$template->output()
は動きます
$template->param('FormField', $cgi->param('FormField'));
のように$cgi->param()メソッドにより提供されるであろうキー/値のペアがそれぞれ指定されたかのように動きます。直接指定したパラメータはassociateされたパラメータよりも優先されます。
associateオプションに無名配列を渡すことにより複数のオブジェクトを関連付けるように指定することが出来ます。それらは指定した順序でパラメータが検索されます:
my $template = HTML::Template->new(filename => 'template.tmpl',
associate => [$query, $other_obj]);
古いassociateCGI()呼び出しはまだサポートされていますが、もう廃棄対象だと考えるべきです。
注意:パラメータ名のマッチングでは大文字・小文字は区別されません。もしCGIオブジェクトに'NAME'と'Name'のような2つのパラメータがあれば、assosiateはでたらめにどちらかを選びます。
<TMPL_LOOP NAME="FOO">
<TMPL_IF NAME="__FIRST__">
This only outputs on the first pass.
</TMPL_IF>
<TMPL_IF NAME="__INNER__">
This outputs on passes that are neither first nor last.
</TMPL_IF>
<TMPL_IF NAME="__LAST__">
This only outputs on the last pass.
<TMPL_IF>
</TMPL_LOOP>
この機能の1つの使い道は、perl関数のjoin()と同じような効果で、"区切り文字"を提供することです。例えば:
<TMPL_LOOP FRUIT>
<TMPL_IF __LAST__> and </TMPL_IF>
<TMPL_VAR KIND><TMPL_UNLESS __LAST__>, <TMPL_ELSE>.</TMPL_UNLESS>
</TMPL_LOOP>
これは(ブラウザでは)以下のようになります:
Apples, Oranges, Brains, Toes, and Kiwi.
もちろん適切はparam()呼び出しが与えられば。注意:ループに1つだけ渡されると_FIRST_と_LAST_はTRUEに設定されますが、_INNER_は設定されません。
例:
my $template = HTML::Template->new( filename => 'file.tmpl',
path => [ '/path/to/templates',
'/alternate/path'
]
);
注意:pathリストでのパスはUNIXパスのように、スラッシュ文字('/')で区切られて、表現されなければなりません。
例:
This is a normal variable: <TMPL_VAR NORMAL>.<P>
<TMPL_LOOP NAME=FROOT_LOOP>
Here it is inside the loop: <TMPL_VAR NORMAL><P>
</TMPL_LOOP>
通常これは、ループの外にある<TMPL_VAR NORMAL>の値がループの内側では使えないために、期待した通りには動きません。
param()
はいくつかの方法で呼び出されます。
1) テンプレートでのパラメータのリストを返す:
my @parameter_names = $self->param();
2) パラメータに設定された値を返す:
my $value = $self->param('PARAM');
3) パラメータに値を設定する:
# 単純なTMPL_VAR:
$self->param(PARAM => 'value');
# 呼ばれるとスカラの値を返すサブルーチンへの
# リファレンス。
$self->param(PARAM => sub { return 'value' });
# そしてTMPL_LOOP:
$self->param(LOOP_PARAM =>
[
{ PARAM => VALUE_FOR_FIRST_PASS, ... },
{ PARAM => VALUE_FOR_SECOND_PASS, ... }
...
]
);
4) 複数のパラメータを設定する:
# 単純なTMPL_VAR:
$self->param(PARAM => 'value',
PARAM2 => 'value'
);
# いくつかのTMPL_LOOPで:
$self->param(PARAM => 'value',
PARAM2 => 'value',
LOOP_PARAM =>
[
{ PARAM => VALUE_FOR_FIRST_PASS, ... },
{ PARAM => VALUE_FOR_SECOND_PASS, ... }
...
],
ANOTHER_LOOP_PARAM =>
[
{ PARAM => VALUE_FOR_FIRST_PASS, ... },
{ PARAM => VALUE_FOR_SECOND_PASS, ... }
...
]
);
5) ハッシュ・リファレンスを使って複数のパラメータを設定:
$self->param(
{
PARAM => 'value',
PARAM2 => 'value',
LOOP_PARAM =>
[
{ PARAM => VALUE_FOR_FIRST_PASS, ... },
{ PARAM => VALUE_FOR_SECOND_PASS, ... }
...
],
ANOTHER_LOOP_PARAM =>
[
{ PARAM => VALUE_FOR_FIRST_PASS, ... },
{ PARAM => VALUE_FOR_SECOND_PASS, ... }
...
]
}
);
clear_params()すべてのパラメータをundefに設定します。他でもない、内部的には便利です!
output()output()
はテンプレートの最終結果を返します。ほとんどの場合、以下のようにこれを出力したいでしょう:
print $template->output();
outputが呼ばれると、<TMPL_VAR NAME=name>のそれぞれはparam()を通して"name"に代入された値で置き換えられます。
もし名前付きのパラメータの設定をはずされたら、単に''で置きかえられます。<TMPL_LOOPS>はパラメータセット毎に1度評価され(are evaluated)、それぞれの出力を蓄積します。
気にしているかもしれないので言っておきますが、output()を呼ぶことはTemplateオブジェクトの状態を変更しないことを保証されています。この属性はループの内部での実装にとってとても重要です。
query()このメソッドはテンプレート構造についての情報を取得することを可能にします。いくつかの方法で呼ぶことができます。queryの最も簡単な使い方は、nameオプションを使って、テンプレートにパラメータ名があるかをチェックすることです:
if ($template->query(name => 'foo')) {
# テンプレートにタイプに関係無くFOOという
# 名前があれば何かする
}
これと同じ使い方はパラメータのタイプを返します。タイプはタグから頭の'TMPL_'を引いたものと同じです。例えば、TMPL_VARパラメータはquery()からは'VAR'を返します。
if ($template->query(name => 'foo') eq 'VAR') {
# FOOがあり、それがTMPL_VARであれば何かする
}
TMPL_IFとTMPL_UNLESSに結び付けられている変数はTMPL_LOOPで使われていない限り、'VAR'で示されます。TMPL_LOOPで使われていれば、'LOOP'を返します。
query()はループの内側(さらにループの内側のループの内側)のパラメータのリストを取得することも可能にします。例えば:
<TMPL_LOOP NAME="EXAMPLE_LOOP">
<TMPL_VAR NAME="BEE">
<TMPL_VAR NAME="BOP">
<TMPL_LOOP NAME="EXAMPLE_INNER_LOOP">
<TMPL_VAR NAME="INNER_BEE">
<TMPL_VAR NAME="INNER_BOP">
</TMPL_LOOP>
</TMPL_LOOP>
そしていくつかのqueryの呼び出し:
# 'LOOP'を返す $type = $template->query(name => 'EXAMPLE_LOOP');
# ('bop', 'bee', 'example_inner_loop')を返す
@param_names = $template->query(loop => 'EXAMPLE_LOOP');
# 両方とも'VAR'を返す $type = $template->query(name => ['EXAMPLE_LOOP', 'BEE']); $type = $template->query(name => ['EXAMPLE_LOOP', 'BOP']);
# そしてこれは'LOOP'を返す
$type = $template->query(name => ['EXAMPLE_LOOP',
'EXAMPLE_INNER_LOOP']);
# そして最後にこれは(('inner_bee', 'inner_bop')を返す
@inner_param_names = $template->query(loop => ['EXAMPLE_LOOP',
'EXAMPLE_INNER_LOOP']);
# 存在しないパラメータにはundefを取得します # これはundefを返します $type = $template->query(name => 'DWEAZLE_ZAPPA');
# loopをループでないパラメータ名に呼び出すとエラーを発生します。 # これはdieします: $type = $template->query(loop => 'DWEAZLE_ZAPPA');
上記のように、loopオプションはパラメータ名のリストを返し、nameもloopもループの内側のパラメータを参照するために配列リファレンスを取ります。loopでないパラメータでloopを使うとエラーになります。
返されるすべての名前は小文字で、タイプは大文字であることに注意してください。
param()、query()と同じように、引数を指定しないと、テンプレートでのトップ・レベルのすべてのパラメータ名を返します。
よりよく理解されるためにperldocのFAQセクションを始めました。私にemailを送る前に、どうかここをご覧下さい。
1) HTML::Templateについて議論したり、そして/またはヘルプの場所はありますか?
HTML::Templateのためのメーリング・リストがhtmltmpl@lists.vm.comがあります。空のメッセージをhtmltmpl-subscribe@lists.vm.com に送って参加してください!
2) <TMPL_XXX>のためのサポートが欲しいんです!どうすればいいんでしょう?
たぶん。私はメーリング・リストでHTML::Templateのためのアイデアについて議論することを皆さんに勧めます。新しいタグが、HTMLテンプレートを使用するための高速で、軽量なシステムを提供するというHTML::Templateの使命にどのようにフィットするのかを説明する準備をしておいてください。
注意:言われた追加をプログラムに当てはめ、最新バージョンのHTML::Templateへのパッチの形で提供すれば、間違い無く潜在的な反対者を弱くさせるでしょう!
3) バグを見つけました.修正してもらえますか?
ものによります。HTML::Templateのバージョン、テスト・スクリプトとテスト・テンプレートを送りましたか?そうであれば、たぶん間違い無いでしょう。
もしあなたが本当に大胆であれば、HTML::Templateはパブリックに利用可能なCVSサーバを持っています。詳細についてはパブリックなCVSサーバ・セクションをご覧下さい。
4) メイン・テンプレートからの<TMPL_VAR>が<TMPL_LOOP>の内側で機能しません!なぜ?
これは予定されている動きです。<TMPL_LOOP>は、Perlでのサブルーチン呼び出しが"my"変数のために別のスコープを導入するのと同じように、<TMPL_VAR>のために別のスコープを導入します。
<TMPL_VAR>をグローバルにしたければ、new()を呼び出すときに'global_vars'を設定することが出来ます。new()の'global_vars'オプションのドキュメントについては上記をご覧下さい。
5) なぜ/t/iではなく/[Tt]/を使うのですか?醜いです!
簡単です- 大文字小文字を無視したマッチのスィッチは効率的ではありません。"Mastering Regular Expressions"(詳説 正規表現) O'Reilly Press によると、/[Tt]/は/t/iにくらべてより速く、よりスペースを有効に使います−文字列の長さの倍程度。//iは基本的に文字列にlc()をおこない、一時的なコピーをメモリに保持します。
これを変更するとき、そしてそれは5.6開発シリーズですが、私は喜んで//iを使います。信じてください、[Tt]がぞっとするほど醜いことは私もわかっています。
6) chacheモードとmod_perlを使ってテンプレートを予めロードするにはどのようにすればできますか?
startup.plに以下のようなものを追加します:
use HTML::Template; use File::Find;
print STDERR "Pre-loading HTML Templates...\n";
find(
sub {
return unless /\.tmpl$/;
HTML::Template->new(
filename => "$File::Find::dir/$_",
cache => 1,
);
},
'/path/to/templates',
'/another/path/to/templates/'
);
あなたがあなたのテンプレートに使用している拡張子を指定するように"return unless"行を変更する必要があることに注意してください。わかっているでしょうが、私(I)は'.tmpl'を使っています。
1つの潜在的な問題:"/path/to/templates"は、HTML::Template->new()を呼ぶときに使うのとまったく同じパスでなければいけません。そうでなければ、cacheは同じファイルであることがわからず、新しいコピーをロードします。スピードはあがらずに、代りに、2倍メモリを使用します。これが起こっているかどうかを調べるには、アプリケーションのなかでcache_debug=>1を設定し、ログに"CACHE MISS"メッセージが無いかを調べます。
7) TMPL_* NAMEにはどんな文字が許されますか?
数字、英字、 '.'、 '/'、 '+'、 '-' そして '_'です。
8) どうすればテンプレートの中からプログラムを実行できますか?
短く言えば:それはできません。長く答えると、HTML::Templateの背後にある基本的な概念−デザインとプログラムは分けるべき−に反するのでするべきではありません。
しかし避けられないことに、人によってはまだそれをすることを欲します。
時にはHTML::Template開発がこの問題に引っかかっているようにも見えるので、私は妥協しようと思います。テンプレートの作者が任意のperlスクリプトをテンプレートの中から評価(evalutate)することを可能にするメソッドがあります。
まず、すべてのデザイナに彼らが"program.pl"という名前のperlスクリプトを実行したいとき、以下のようなタグを使うように言います:
<TMPL_VAR NAME="__execute_program.pl__">
そして、すべてのプログラマにHTML::Template::newを直接呼び出す代りに、このサブルーチンを呼び出させます。同じパラメータを使っていますが、プログラム実行を取得しています。
sub new_template {
# テンプレート・オブジェクトを取得
my $template = HTML::Template->new(@_);
# プログラムのパラメターを見つけ、それらを埋め込みます
my @params = $template->param();
for my $param (@params) {
if ($param =~ /^__execute_(.*)__$/) {
$template->param($param, do($1));
}
}
# Templateオブジェクトを返す
return $template;
}
この方法で呼ばれるプログラムは出力が入っている文字列を返さなければなりません。さらに複雑なサブループンはスクリプトからSTDOUTを捕らえるように書かれるかもしれません、しかしこれはFAQに入るくらい十分に簡単なものです。他の改造は、query()を使ってループの内側でのプログラム実行を可能にすることです。
私はバグについて何も気がついていません−もし見つけたらメーリング・リストに参加して、それを伝えてください(htmltmpl@lists.vm.com)。HTML::Templateメーリング・リストにはhtmltmpl-subscribe@lists.vm.comに空のメールを送ることによって参加できます。もちろんバグについて私に直接メールする(sam@tregar.com)こともできます。しかし私は言われたバグレポートを転送する権利を保持しています。
バグ・レポートを送信するときには問題を証明する、モジュールのVERSION、テスト・スクリプト、そしてテスト・テンプレートを間違い無く入れてください!
もしあなたが本当に大胆であれば、HTML::Templateはパブリックに利用可能なCVSサーバを持っています。詳細についてはパブリックなCVSサーバ・セクションをご覧下さい。
このモジュールはVanguard Mediaでの私の上司 Jesse Erlbaum (jesse@vm.com)の頭脳の産物です。このモジュールでのほとんどのオリジナルのアイデア-<TMPL_LOOP>-は完全に彼のものです。
以下の方々からは修正、バグ・レポート、最適化そしてアイデアを惜しみなくいただきました:
Richard Chen Mike Blazer Adriano Nagelschmidt Rodrigues Andrej Mikus Ilya Obshadko Kevin Puetz Steve Reppucci Richard Dice Tom Hukins Eric Zylberstejn David Glasser Peter Marelas James William Carlson Frank D. Cringle Winfried Koenig Matthew Wickline Doug Steinwand Drew Taylor Tobias Brox Michael Lloyd Simran Gambhir Chris Houser <chouser@bluweb.com> Larry Moore Todd Larason
どうもありがとう!
HTML::Template はSourceForge (www.sourceforge.net)によって提供されるパブリックにアクセスすることができるCVSサーバを持っています。それには http://sourceforge.net/cvs/?group_id=1075にいくことによりアクセスすることができます。トライしてみてください。
(原文のまま)
Sam Tregar, sam@tregar.com (you can also find me on the mailing list at htmltmpl@lists.vm.com - join it by sending a blank message to htmltmpl-subscribe@lists.vm.com).
(原文のまま)
HTML::Template : A module for using HTML Templates with Perl Copyright (C) 2000 Sam Tregar (sam@tregar.com)
This module is free software; you can redistribute it and/or modify it under the terms of either:
a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or
b) the "Artistic License" which comes with this module.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the Artistic License for more details.
You should have received a copy of the Artistic License with this module, in the file ARTISTIC. If not, I'll be glad to provide one.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
ご意見、ご質問はこちらの掲示板で受け付けています。
またメールは河馬屋(Nifty)にお願いします。