Text::MicroTemplate::Extended::ja - Japanese document
use Text::MicroTemplate::Extended; my $mt = Text::MicroTemplate::Extended->new( include_path => ['/path/to/document_root'], template_args => { c => $c, stash => $c->stash, }, ); $mt->render('content'); # render file: /path/to/document_root/content.mt
Text::MicroTemplate::Extended は Text::MicroTemplate::File にをベースにいくつかの機能を追加した拡張モジュールです。 基本的な機能については Text::MicroTemplate::File のドキュメントを参照ください。
テンプレートの継承は Django テンプレートなどで採用されているテンプレート再利用の仕組みです。 Text::MicroTemplate::Extended ではこのテンプレート継承の仕組みをほぼそのまま使うことが可能です。
テンプレート継承はテンプレートのひな形となる親テンプレートの中でいくつか再定義可能なブロックを定義しておくと、それを子テンプレートで自由に再定義することができるという機能です。
テンプレートの継承を理解するには、まず例を挙げるのが一番でしょう:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title><? block title => sub { ?>My amazing site<? } ?></title> </head> <body> <div id="sidebar"> <? block sidebar => sub { ?> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> <? } ?> </div> <div id="content"> <? block content => sub {} ?> </div> </body> </html>
このテンプレートは、単純な 2 カラム形式のページで使うような HTML のスケルトンドキュメントです。これを base.mt と呼びましょう。空のブロックをコンテンツで埋めるのは「子 (child)」のテンプレートの仕事です。
この例では、 <? block ?> タグを使って 3 つのブロックを定義し、子テンプレートが値を埋められるようにしています。 block タグの役割は、テンプレート中のタグで囲まれた部分を子テンプレートでオーバライドできることをテンプレートエンジンに知らせることにあります。
<? block ?
子テンプレートは以下のようになります:
? extends 'base' <? block title => sub { ?>My amazing blog<? } ?> ? block content => sub { ? for my $entry (@$blog_entries) { <h2><?= $entry->title ?></h2> <p><?= $entry->body ?></p> ? } # endfor ? } # endblock
<? extends 'base' ?> タグ(または ? extends 'base')が継承のカギです。このタグはテンプレートエンジンに対して、自分自身が他のテンプレートを拡張 (extend) していることを教えます。テンプレートシステムがこのテンプレートを処理する際、システムはまず親となるテンプレート -- ここでは "base.mt" を探します。
<? extends 'base' ?
? extends 'base'
さて、この時点で、テンプレートエンジンは base.mt 内に三箇所の <? block ?> が定義されていることに気づき、これらのブロックを子テンプレートの該当するブロックで置き換えます。 blog_entries の値に応じて、出力は以下のようになります:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <link rel="stylesheet" href="style.css" /> <title>My amazing blog</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog/">Blog</a></li> </ul> </div> <div id="content"> <h2>Entry one</h2> <p>This is my first entry.</p> <h2>Entry two</h2> <p>This is my second entry.</p> </div> </body> </html>
子テンプレートには sidebar ブロックが定義されていないので、親テンプレートの値がそのまま使われます。親テンプレートの <? block ?> タグの内容は、常にフォールバックの値として使われます。
テンプレートの継承は必要に応じて何段階にもできます。継承を使うよくある場合の一つに、以下のような三段階のアプローチがあります:
サイトの主なルック&フィールを決める base.mt テンプレートを作成します。
サイトの各「セクション」ごとに base_SECTIONNAME.mt テンプレートを作成します。たとえば、 base_news.mt, base_sports.mt といった具合です。これらのテンプレートでは base.mt を拡張して、セクション固有のスタイルやデザインを取り込んでおきます。
ニュース記事やブログエントリといった各種ページ用の個々のテンプレートを作成します。これらのテンプレートでは適切なセクションテンプレートを拡張します。
このようなアプローチを取れば、コードの最利用性を最大限に高め、セクション毎のナビゲーションのような項目を簡単に共通のコンテンツ領域に追加できます。
継承を扱うときの小技をいくつか挙げておきます:
テンプレートで <? extends ?> を使う場合、1テンプレート中にこの命令は一度しか使用できないことに注意してください。複数この命令があった場合は、後ろのものが優先されます。
<? extends ?
ベースのテンプレートで <? block ?> を多用すればするほど、よりよいテンプレートになります。子テンプレートは親テンプレートのブロックを必ずしも全て定義しなくてもよいことを思い出して下さい。ブロックをたくさん用意しておき、適切なデフォルト値を入れておいて、子テンプレートで必要な値だけを再定義すればよいのです。フックは少ないよりも沢山ある方がよいのです。
同じような内容を含むテンプレートをいくつも作っていることに気づいたら、それはすなわちその内容を親テンプレートの <? block ?> に入れるべきだということです。
親テンプレートのブロックに入っているコンテンツを取り出す必要がある場合、 <?= super() ?> とするとうまくいきます。親テンプレートのブロックをオーバライドするのではなく、内容を追加したい場合に便利です。 <?= super() ?> で挿入されたデータは、通常、親テンプレートで既にエスケープされているので、自動的にエスケープされません
<?= super() ?>
可読性を高めるために、例えば以下のように、 <? } # endblock ?> にブロックの 名前 を指定できます:
<? } # endblock ?
<? block content => sub { ?> ... <? } # endblock content ?> 大きなテンプレートの編集で、どこで C<<? block ?>> タグが閉じているか探すのに便利です。
最後に、同じテンプレート中に同じ名前の <? block ?> を複数定義できないことに注意して下さい。この制限は、ブロックタグが「双方向」に作用するため、すなわち、あるブロックタグは何らかの値を埋めるための穴であるだけでなく、穴を埋める 親テンプレートの コンテンツも定義しているために存在しています。同じ名前の <? block ?> が一つのテンプレート内に複数あると、そのテンプレートの親テンプレートは、該当するブロックの内容を子テンプレートのどの <? block ?> 設定で置き換えればよいのか分からなくなってしまいます。
Text::MicroTemplate::Extended オブジェクトの初期化時に template_args 引数でテンプレートに渡したい変数をハッシュリファレンスとして登録しておくと、テンプレート展開時にその引数に名前付き変数としてアクセスすることができます。
template_args
my $mf = Text::MicroTemplate::Extended->new( template_args => { foo => 'bar', }, ... );
としておくと
<?= $foo ?>
で bar という出力が得られます。
bar
また、以下のようにコードリファレンスを渡すとテンプレート実行時に実行されたものが引数として展開されます。
my $mf = Text::MicroTemplate::Extended->new( template_args => { foo => sub { $self->get_foo() } }, ... );
上記のように引数を設定すると <?= $foo ?> で $self->get_foo の結果を表示することができます。 この機能はテンプレートオブジェクト初期化時には引数に与えたいものが存在しない場合など、引数をあとから渡す場合に有効です。
<?= $foo ?
$self->get_foo
マクロ機能は名前付き引数に似ていますが、こちらは引数をつくるかわりに関数をテンプレートに渡します。
my $mh = Text::MicroTemplate::Extended->new( macro => { hello => sub { return 'Hello World!' }, }, ... );
このコードはテンプレート内で hello と言う関数を使用できるようにします。
<?= hello() ?> # => 'Hello World!'
この機能は $key => $coderef のような構造のハッシュリファレンスを渡すことを想定していますが、value部分に通常のコードリファレンス以外の変数を渡すとそれを自動的にコードリファレンスでくくって使用します。 上記の hello マクロはこのように書き換えても同じ意味になります。
$key => $coderef
hello
my $mh = Text::MicroTemplate::Extended->new( macro => { hello => 'Hello World!', }, ... );
オリジナルの Text::MicroTemplate::File ではテンプレートファイルをレンダリングする際に
$mf->render_file('template_name.mt');
とファイル名をフルネームで指定する必要がありました。
しかし、実用上は .mt などのようにテンプレート用の拡張子をつけて使用する場合がほとんどです。そのため、Text::MicroTemplate::Extended では extension というオプションを用意していて、
.mt
extension
my $mf = Text::MicroTemplate::Extended->new( extension => '.mt', ... );
などのように初期化すると
$mf->render_file('template_name');
というコードで template_name.mt を読み込むようにすることができます。また、上記の「テンプレートの継承」でもこのオプションが使用され、extension => '.mt' の場合は <? extends 'base' ?> というコードは base.mt をロードします。
template_name.mt
extension => '.mt'
base.mt
このオプションはデフォルトでは .mt に設定されています。
Text::MicroTemplate::File では render_file メソッドでテンプレートファイルをレンダリング、render メソッドでスカラー変数などに定義されたテンプレートをレンダリングというような使い分けが可能だったのですが、Text::MicroTemplate::Extended では、テンプレートの継承をサポートするという目的のためテンプレートファイルのレンダリングのみに機能を絞りました。
render_file
render
そのため、Text::MicroTemplate::Extended では render メソッドは render_file メソッドへのショートカットとして動作するようになっています。
$mf->render('template_name'); $mf->render_file('template_name');
は同等の処理を行います。
my $mf = Text::MicroTemplate::Extended->new( extension => '.mt', template_args => { c => $c, stash => $c->stash }, );
Text::MicroTemplate::Extended オブジェクトを初期化します。
使用可能なオプションは以下の通りです:
テンプレートファイルの拡張子を設定します。(デフォルトは .mt です)
テンプレートに渡す引数をハッシュリファレンスで指定します。
テンプレート内で使用するmacroをハッシュリファレンスで指定します。
これ以外のオプションは Text::MicroTemplate::File を参照してください。
$template_name で渡されてテンプレートをレンダリングし、結果を返します。
$template_name
Daisuke Murase <typester@cpan.org>
Copyright (c) 2009 by KAYAC Inc.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
The full text of the license can be found in the LICENSE file included with this module.
To install Text::MicroTemplate::Extended, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Text::MicroTemplate::Extended
CPAN shell
perl -MCPAN -e shell install Text::MicroTemplate::Extended
For more information on module installation, please visit the detailed CPAN module installation guide.