とあるPerl/CGIでできていたシステムを訳あって再構成することになり、Mojolicious+Xslate化するまでにやったことをざっくりと紹介します。
目次
0. 変更前
- Perl/CGI
- CGI.pm等も使わずに本当に生Perl
index.pl
#!/usr/bin/perl
print"Content-type: text/html; \n\n";
my $a = "hoge";
my $b = "fuga";
print << "EOH";
<html>
<head>
<title>タイトル</title>
...
EOH
print "<span>$a</span>\n";
print "<input type=\"text\" name=\"foo\" value=\"$b\" />\n";
print << "EOL";
&create_select();
...
</body>
</html>
EOL
sub create_select {
print "<select name=\"xxx\">\n";
for(my $count=1; $count < 10; $count++){
print "<option value=\"$count\">$count回</option>\n";
}
print "</select>\n";
}
1. CGI.pmの導入
- 何度も
print << "EOL";
していたのがだるい- 一度で済ませる
- 生で
<select>
項目作るのがだるい- $cgi->popup_nemuメソッドの活用
index.pl
#!/usr/bin/perl
use CGI;
my $cgi = new CGI;
print $cgi->header(-charset=>'UTF-8');
my $a = "hoge";
my $b = "fuga";
print << "EOL";
<html>
<head>
<title>タイトル</title>
...
<span>$a</span>
<input type="text" name="foo" value="$b" />
@{[ &create_select() ]}
...
</body>
</html>
EOL
sub create_select {
my @values = (1..10);
my %labels = map { $_ => "$_回" } @values;
my ret = $cgi->pouup_menu(
-name => "xxx",
-values => \@values,
-labels => \%labels
);
$ret;
}
2. Text::Xslateの導入
- ヒアドキュメントで直接変数を埋め込むのだるい
- テンプレートは別途編集したい
とりあえず導入
- まずはテンプレートを文字列で定義してレンダリングする
index.pl
#!/usr/bin/perl
use CGI;
use Text::Xslate;
my $cgi = new CGI;
print $cgi->header(-charset=>'UTF-8');
my $template << "EOL";
<html>
<head>
<title>タイトル</title>
...
<span><: \$a :></span>
<input type="text" name="foo" value="<: \$b :>" />
@{[ &create_select() ]}
...
</body>
</html>
EOL
my $tx = Text::Xslate->new();
printe $tx->render_string(
$template,
{
a => "hoge",
b => "fuga",
}
);
sub create_select {
my @values = (1..10);
my %labels = map { $_ => "$_回" } @values;
my ret = $cgi->pouup_menu(
-name => "xxx",
-values => \@values,
-labels => \%labels
);
$ret;
}
@{[ ... ]}
での埋め込みをやめる
- Xslateの関数機能を使い、レンダリング時にPerlのサブルーチンを呼び出す
index.pl
#!/usr/bin/perl
use CGI;
use Text::Xslate;
my $cgi = new CGI;
print $cgi->header(-charset=>'UTF-8');
my $template << "EOL";
<html>
<head>
<title>タイトル</title>
...
<span><: \$a :></span>
<input type="text" name="foo" value="<: \$b :>" />
<: create_select() | raw :>
...
</body>
</html>
EOL
my $tx = Text::Xslate->new(
function => {
create_select => \&create_select,
}
);
printe $tx->render_string(
$template,
{
a => "hoge",
b => "fuga",
}
);
sub create_select {
my @values = (1..10);
my %labels = map { $_ => "$_回" } @values;
my ret = $cgi->pouup_menu(
-name => "xxx",
-values => \@values,
-labels => \%labels
);
$ret;
}
テンプレートを外部ファイル化
- テンプレートは別管理にしたい
- 編集の容易さの確保
- $をエスケープするのがだるい
- Xslateのrenderメソッドで外部ファイルに定義したテンプレートを指定
index.tx
<html>
<head>
<title>タイトル</title>
...
<span><: $a :></span>
<input type="text" name="foo" value="<: $b :>" />
<: create_select() | raw :>
...
</body>
</html>
index.pl
#!/usr/bin/perl
use CGI;
use Text::Xslate;
my $cgi = new CGI;
print $cgi->header(-charset=>'UTF-8');
my $tx = Text::Xslate->new(
function => {
create_select => \&create_select,
}
);
printe $tx->render(
'index.tx',
{
a => "hoge",
b => "fuga",
}
);
sub create_select {
my @values = (1..10);
my %labels = map { $_ => "$_回" } @values;
my ret = $cgi->pouup_menu(
-name => "xxx",
-values => \@values,
-labels => \%labels
);
$ret;
}
3. Mojolicious導入
- ちゃんとしたアプリにするには生CGIはつらい
- Perlで人気のWAFって何?
- Mojolicios
- CGI.pmさようなら
templates/index.html.tx
<html>
<head>
<title>タイトル</title>
...
<span><: $a :></span>
<input type="text" name="foo" value="<: $b :>" />
<select name="xxx">
: for [1..10] -> $value {
<option value="<: $value :>">
<: $value :>回
</option>
: }
</select>
...
</body>
</html>
index.pl
#!/usr/bin/perl
use Mojolicious::Lite;
use Text::Xslate;
plugin 'xslate_renderer' => {
template_options => {
# これを設定しないとplファイルのフォルダー内にあるtmpフォルダーを使おうとする
cache_dir => $Text::Xslate::DEFAULT_CACHE_DIR
},
};
get '/' => sub {
my $c = shift;
$c->render(
a => "hoge",
b => "fuga",
);
} => 'index';
app->start;
4. あとはがんばる
- 画面増やしたり、アクション増やしたり
- Mojoliciousはモデルバインディングはないのでがんばったり
- 画面の共通レイアウトを親テンプレート化したり
- 複数画面で使う
select
要素をテンプレート化したり - etc...