Template-ToolkitのWRAPPERでレイアウト制御

my $tt = Template->new(
    LOAD_TEMPLATES => [ Template::Provider::Encoding->new(INCLUDE_PATH => 'templates') ],
    STASH          => Template::Stash::ForceUTF8->new,
    PROCESS        => $c->{layout},
);
$tt->process($c->{template}, $c->{stash}) || die $tt->error()."\n";

みたいにTTのコンストラクタにPROCESSでレイアウトテンプレート投げて、テンプレート側で

[% META title = 'ページのタイトル' %]

みたいにして、レイアウトから

<title>[% template.title %]</title>

で呼び出せばOK。そんな風に思っていた時期が俺にもありました…

これで進めてたら、METAで渡す値には変数を入れることが出来ないことが判明。マニュアルにも思いっきり

it's not possible to interpolate other variables values into META variables

と書かれていて終了ですよ。回避策も探してはみたけど、やっぱりどうにもなりません。

以前、ウノウラボで「SmartyでRailsライクなレイアウトテンプレートを使う」を書いた時に、「TTだとWRAPPER使って出来る」みたいなことを見かけたので、それを手掛かりに探ってみると、いい感じのアプローチを発見。

WRAPPERだけのためにテンプレートを用意するのはイヤだったので、変態呼ばわりされている4番の方法を採用。この業界、変態は褒め言葉ですから。結局、Perl側のコードはこんな感じ。

my $tt = Template->new(
    LOAD_TEMPLATES => [ Template::Provider::Encoding->new(INCLUDE_PATH => 'templates') ],
    STASH          => Template::Stash::ForceUTF8->new,
    WRAPPER        => [ \ '[% IF LAYOUT == "none"; content; ELSIF LAYOUT; content WRAPPER $LAYOUT; ELSE; content WRAPPER layout.tt2; END%]' ]
);
$tt->process($c->{template}, $c->{stash}) || die $tt->error()."\n";

layout.tt2をこんな感じで用意して、

<html>
 <head>
  <title>[% TITLE %]</title>
 </head>
 <body>
  <div id="header"></div>
  <div id="content">[% content %]</div>
  <div id="footer"></div>
 </body>
</html>

コンテンツのテンプレートで、

[% TITLE = "$keywordの検索結果" -%]
<p>[% keyword %]で検索しました</p>

みたいにしてやればOK。

レイアウトの制御は、

[% LAYOUT = 'layout_login.tt2' -%]

みたいに任意のテンプレートを指定したり、

[% LAYOUT = 'none' -%]

すればレイアウトを適用しない、てな具合にしてみました。今のところ、これで快適。