LoginSignup
6
7

More than 5 years have passed since last update.

Perl/CGIをMojolicious+Xslate化した話

Last updated at Posted at 2016-08-31

とある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...
6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7