Catalyst::Helper::View::TTSite を使ってみたら、雛形のテンプレートで TT の WRAPPER がみたことがない使われ方をしていたので、調べてみたら TT の Automatic Wrapper という仕組みだった、という話。
今までの自分の TT の使い方。
普段自分が Web アプリなんかで TT を使う時の使い方は、header.tt と footer.tt とか作って、tt_process で指定するテンプレがそいつらを含めてるという、↓のような感じ。
header.tt。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>[% title %]</title>
</head>
<body>
footer.tt。
<div id="footer">© 2006 ziguzagu</div>
</body>
</html>
で、コントローラーで指定するテンプレ、index.tt とかをこう。
[% INCLUDE header.tt title="タイトル" %]
<p>なかみ</p>
[% INSERT footer.tt %]
これはこれで、header.tt / footer.tt の再利用が出来るのはいい。ただ、
- 各テンプレート内でHTMLの開始タグと終了タグの対応がとれてない
- ベースになるテンプレート全部で同じ INCLUDE や PROCESS / INSERT を書く必要がある
とかいったあたりがあんまり美しくないなぁ、とは思ってたり。でもそこで思考停止…。
そこで、AutoWrapper。
TT のインスタンスを作るときに、PRE_PROCESS や POST_PROCESS オプションにテンプレートを指定するのと同じ形で、WRAPPER オプションに一番外側になるテンプレートを指定すると、tt_process で生成される出力が、WRAPPER で指定したテンプレの content になる、というのが TTSite の雛形をみて知った。
たとえば、
wrapper.pl
#!/usr/bin/perl
use strict;
use warnings;
use Template;
my $tt = Template->new({
WRAPPER => 'wrapper.tt',
});
$tt->process('content.tt');
というのを作って、wrapper.tt には HTML の全体像を記述。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>[% template.title %]</title>
</head>
<body>
[% content %]
</body>
<div class="footer">© 2006 ziguzagu</div>
</html>
content.tt には、[% content %] に入れたい部分を記述。
[% META title = 'Wrapper Test' %]
<p>Hello Wrapper!!</p>
で、実行した結果は、こうなる。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Wrapper Test</title>
</head>
<body>
<p>Hello Wrapper!!</p>
</body>
<div class="footer">© 2006 ziguzagu</div>
</html>
META が実はいい感じ(METAもほとんど使ったこと無かった…)。
WRAPPER を入れ子にしてみる。
WRAPPER は複数テンプレートを入れ子にも出来る。
wrapper.tt をこんな風に。
<!-- BEGIN auto wrapper -->
[% content WRAPPER html.tt + inner.tt %]
<!-- END auto wrapper -->
親テンプレの html.tt。
<!-- BEGIN html.tt -->
<title>
[% template.title %]
</title>
<content>
[% content -%]
</content>
<!-- END html.tt -->
これの content に、次に指定した inner.tt が入る。
inner.tt。
<!-- BEGIN inner.tt -->
[% content %]
<!-- END inner.tt -->
inner.tt の content には、tt_process で指定した content.tt が入ってくる。 で、結果はこうなる。
<!-- BEGIN auto wrapper -->
<!-- BEGIN html.tt -->
<title>
Wrapper Test
</title>
<content>
<!-- BEGIN inner.tt -->
<p>Hello Wrapper!!</p>
<!-- END inner.tt -->
</content>
<!-- END html.tt -->
<!-- END auto wrapper -->
content をどんどん入れ子に。いいね。
ということは
個別のページ専用の分岐とかを META とかの指定でうまい具合にやれば、無駄な毎回同じテンプレ INCLUDE とかなくなるような気がする。。。
ちなみに、↓の本の Chapter.2 に、『Using an Automatic Wrapper Template』という項がしっかりあって、ちゃんと解説されているという事実。ttree 使ったサンプルとかも。TTSite 使うまでは目もくれなかった。。。