The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Text::MicroTemplate::Extended::ja - Japanese document

SYNOPSIS

    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

DESCRIPTION

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 タグの役割は、テンプレート中のタグで囲まれた部分を子テンプレートでオーバライドできることをテンプレートエンジンに知らせることにあります。

子テンプレートは以下のようになります:

    ? 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" を探します。

さて、この時点で、テンプレートエンジンは 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 ?> タグの内容は、常にフォールバックの値として使われます。

テンプレートの継承は必要に応じて何段階にもできます。継承を使うよくある場合の一つに、以下のような三段階のアプローチがあります:

  1. サイトの主なルック&フィールを決める base.mt テンプレートを作成します。

  2. サイトの各「セクション」ごとに base_SECTIONNAME.mt テンプレートを作成します。たとえば、 base_news.mt, base_sports.mt といった具合です。これらのテンプレートでは base.mt を拡張して、セクション固有のスタイルやデザインを取り込んでおきます。

  3. ニュース記事やブログエントリといった各種ページ用の個々のテンプレートを作成します。これらのテンプレートでは適切なセクションテンプレートを拡張します。

このようなアプローチを取れば、コードの最利用性を最大限に高め、セクション毎のナビゲーションのような項目を簡単に共通のコンテンツ領域に追加できます。

継承を扱うときの小技をいくつか挙げておきます:

  • テンプレートで <? extends ?> を使う場合、1テンプレート中にこの命令は一度しか使用できないことに注意してください。複数この命令があった場合は、後ろのものが優先されます。

  • ベースのテンプレートで <? block ?> を多用すればするほど、よりよいテンプレートになります。子テンプレートは親テンプレートのブロックを必ずしも全て定義しなくてもよいことを思い出して下さい。ブロックをたくさん用意しておき、適切なデフォルト値を入れておいて、子テンプレートで必要な値だけを再定義すればよいのです。フックは少ないよりも沢山ある方がよいのです。

  • 同じような内容を含むテンプレートをいくつも作っていることに気づいたら、それはすなわちその内容を親テンプレートの <? block ?> に入れるべきだということです。

  • 親テンプレートのブロックに入っているコンテンツを取り出す必要がある場合、 <?= super() ?> とするとうまくいきます。親テンプレートのブロックをオーバライドするのではなく、内容を追加したい場合に便利です。 <?= super() ?> で挿入されたデータは、通常、親テンプレートで既にエスケープされているので、自動的にエスケープされません

  • 可読性を高めるために、例えば以下のように、 <? } # endblock ?> にブロックの 名前 を指定できます:

        <? block content => sub { ?>
        ...
        <? } # endblock content ?>
    
     大きなテンプレートの編集で、どこで C<<? block ?>> タグが閉じているか探すのに便利です。

最後に、同じテンプレート中に同じ名前の <? block ?> を複数定義できないことに注意して下さい。この制限は、ブロックタグが「双方向」に作用するため、すなわち、あるブロックタグは何らかの値を埋めるための穴であるだけでなく、穴を埋める 親テンプレートの コンテンツも定義しているために存在しています。同じ名前の <? block ?> が一つのテンプレート内に複数あると、そのテンプレートの親テンプレートは、該当するブロックの内容を子テンプレートのどの <? block ?> 設定で置き換えればよいのか分からなくなってしまいます。

名前付き引数

Text::MicroTemplate::Extended オブジェクトの初期化時に template_args 引数でテンプレートに渡したい変数をハッシュリファレンスとして登録しておくと、テンプレート展開時にその引数に名前付き変数としてアクセスすることができます。

    my $mf = Text::MicroTemplate::Extended->new(
        template_args => { foo => 'bar', },
        ...
    );

としておくと

    <?= $foo ?>

bar という出力が得られます。

また、以下のようにコードリファレンスを渡すとテンプレート実行時に実行されたものが引数として展開されます。

    my $mf = Text::MicroTemplate::Extended->new(
        template_args => { foo => sub { $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 マクロはこのように書き換えても同じ意味になります。

    my $mh = Text::MicroTemplate::Extended->new(
        macro => {
            hello => 'Hello World!',
        },
        ...
    );

拡張子の省略

オリジナルの Text::MicroTemplate::File ではテンプレートファイルをレンダリングする際に

    $mf->render_file('template_name.mt');

とファイル名をフルネームで指定する必要がありました。

しかし、実用上は .mt などのようにテンプレート用の拡張子をつけて使用する場合がほとんどです。そのため、Text::MicroTemplate::Extended では extension というオプションを用意していて、

    my $mf = Text::MicroTemplate::Extended->new(
        extension => '.mt',
        ...
    );

などのように初期化すると

    $mf->render_file('template_name');

というコードで template_name.mt を読み込むようにすることができます。また、上記の「テンプレートの継承」でもこのオプションが使用され、extension => '.mt' の場合は <? extends 'base' ?> というコードは base.mt をロードします。

このオプションはデフォルトでは .mt に設定されています。

renderメソッドの置き換え

Text::MicroTemplate::File では render_file メソッドでテンプレートファイルをレンダリング、render メソッドでスカラー変数などに定義されたテンプレートをレンダリングというような使い分けが可能だったのですが、Text::MicroTemplate::Extended では、テンプレートの継承をサポートするという目的のためテンプレートファイルのレンダリングのみに機能を絞りました。

そのため、Text::MicroTemplate::Extended では render メソッドは render_file メソッドへのショートカットとして動作するようになっています。

    $mf->render('template_name');
    $mf->render_file('template_name');

は同等の処理を行います。

METHODS

new (%options)

    my $mf = Text::MicroTemplate::Extended->new(
        extension     => '.mt',
        template_args => { c => $c, stash => $c->stash },
    );

Text::MicroTemplate::Extended オブジェクトを初期化します。

使用可能なオプションは以下の通りです:

extension

テンプレートファイルの拡張子を設定します。(デフォルトは .mt です)

template_args

テンプレートに渡す引数をハッシュリファレンスで指定します。

macro

テンプレート内で使用するmacroをハッシュリファレンスで指定します。

これ以外のオプションは Text::MicroTemplate::File を参照してください。

render ($template_name, @args)

render_file ($template_name, @args)

$template_name で渡されてテンプレートをレンダリングし、結果を返します。

INTERNAL METHODS

build

eval_builder

template_args

extension

render_context

AUTHOR

Daisuke Murase <typester@cpan.org>

COPYRIGHT AND LICENSE

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.