【perlメモ】Text::MicroTemplateモジュールを使ってみる。
テンプレート機能を実現する為のCPANモジュールのText::MicroTemplateを使ってみた。用途としては、プログラムとテンプレートを分離するのに使う。他のモジュールに依存していないので気軽に使えて便利。
個人的に使ってみた感じの長所と短所
長所
- テンプレートモジュールの中では軽量高速。
- 自動でエスケープしてくれるのでXSS等脆弱性対策が出来る。セキュリティー的にちょっと安心。
- ページデザインする人とプログラミングをする人が別の場合には便利。
- ページデザインが分離できるのでデザイン修正時にプログラムソースを弄る必要がなく安全。
- ページデザインを分離するとページ生成部分をソース上から探す手間が無くて便利。
- テンプレート中にコードがかけるので色々できる。
- テンプレート中からプログラム中のサブルーチンも呼べるので便利。
短所
- 勝手にエスケープしてくれるのは便利だが大抵の場合内部で自分でやっているのでかえって無駄になる場合も多い。
- わざわざ分ける手間が面倒。
- デザインする人とプログラムをする人がわかれていない場合逆に面倒で手間がかかる。
- 分離してモジュールを読み込む分遅くなるだろう。
- 下手にテンプレート中にコードを埋め込むとかえって複雑になってしまう可能性がある。
個人で作るプログラム程度であれば別に無くても困らないモジュールではある。仕事などではデザイナーとプログラマが分かれている場合も多いのでそういう場合は重宝すると思う。
Text::MicroTemplate – search.cpan.org
use Text::MicroTemplate qw(:all);
# compile template, and render
$renderer = build_mt(‘hello, <?= $_[0] ?>’);
$html = $renderer->(‘John’)->as_string;# or in one line
$html = render_mt(‘hello, <?= $_[0] ?>’, ‘John’)->as_string;# complex form
$mt = Text::MicroTemplate->new(
template => ‘hello, <?= $query->param(‘user’) ?>’,
);
$code = $mt->code;
$renderer = eval << "…" or die $@;
sub {
my \$query = shift;
$code->();
}
…
$html = $renderer->(CGI->new)->as_string
cpanのサンプルは上の通り。
テンプレートの文法は下のようになっている
# output the result of expression with automatic escape
<?= $expr ?> (tag style) 行中に埋め込むとき
?= $expr (per-line) 一行丸々の時
# execute perl code (tag style)
普通にプログラム中で書いたサブルーチンをテンプレート中で呼べる
<? foo() ?>
? foo()
# comment (tag style)
<?# comment ?>
?# comment
自分で試した限りでは上は
? # comment
にしないとエラーになる。
# loops
<ul>
? for my $item (@list) {
<li><?= $item ?></li>
? }
</ul>
Text::MicroTemplate::File – search.cpan.org
use Text::MicroTemplate::File;
our $mtf = Text::MicroTemplate::File->new(
include_path => [ $path1, $path2, … ],
use_cache => 1,
);# render
$mtf->render_file(‘template.file’, $arg1, $arg2, …);
ファイルからテンプレートを読み込んで使う場合はText::MicroTemplate::Fileを使う。cpanのサンプルは上の通り。
実際にText::MicroTemplate使って作成中のプログラムの抜粋。
search.cgi
use strict;
use warnings;
use utf8;
use Text::MicroTemplate qw(:all);
use Text::MicroTemplate::File;
#ページ表示
my $mtf = Text::MicroTemplate::File->new(include_path => [ ‘mt’ ],use_cache => 1);
my %para = (
‘eKeyword’ => $eKeyword,
‘keyword’ => $keyword,
‘TITLE’ => "${KCFG::DESCRIPTION} – ${KCFG::SITENAME}",
‘SITENAME’ => $KCFG::SITENAME,
‘SITEURL’ => $KCFG::SITEURL,
‘DESCRIPTION’ => $KCFG::DESCRIPTION,
‘pankuzu’ => $pankuzu,
‘sort_link’ => $sort_link,
‘result’ => $result,
‘out’ => $out,
‘gParent’ => $gParent,
‘gCurrent’ => $gCurrent,
‘glist’ => $glist,
‘page’ => $page,
‘copyright’ => $KCFG::copyright,
‘webservice’ => $KCFG::webservice,
‘analytics’ => $KCFG::analytics,
);
my $html = $mtf->render_file(‘search.mt’, {%para});
binmode STDOUT,’:utf8′;
print "Content-type: text/html; charset=utf-8\n\n";
print $html;
search.mt
? # search.mt
? my $r=shift;
? my $skeyword = $r->{keyword};
? # $skeyword =~ / +/,/g;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="content-style-type" content="text/css">
<meta name="description" content="<?= $r->{keyword} ?>の検索結果。<?= $r->{TITLE} ?>">
<meta name="keywords" content="<?= $skeyword ?>,<?= $r->{SITENAME} ?>">
<title><?= $r->{keyword} ?>の検索結果。<?= $r->{TITLE} ?></title>
<link rel="stylesheet" type="text/css" href="/css/search.css">
</head>
<body>
<div id="header_wrapper">
<div id="header_menu">
楽ツール ::
</div>
</div>
<div id="wrapper">
<div id="title"><h1><a href="/"><img src="/img/rakutool.gif" alt="<?= $r->{DESCRIPTION} ?> – <?= $r->{SITENAME} ?>" title="<?= $r->{DESCRIPTION} ?> – <?= $r->{SITENAME} ?>"></a></h1></div>
<div class="panlist"><?= encoded_string($r->{pankuzu}) ?></div>
<div id="sort_link"><?= encoded_string($r->{sort_link}) ?></div>
<div id="bd_L">
<div id="search"><?= encoded_string(form()) ?></div>
<div id="result1"><?= $r->{result} ?></div>
<div id="result2"><?= encoded_string($r->{out}) ?></div>
</div>
(以下略)
エスケープされていない生(raw)データを表示したい場合は、encoded_string関数を使う。
デフォルトをrawデータ表示にするには下のようにexcape_funcにundefを渡してあげると出来る。
#ページ表示
my $mtf = Text::MicroTemplate::File->new(include_path => [ ‘mt’ ],use_cache => 1);
$mtf->escape_func(undef);