Perl入門ゼミ

  1. Perl
  2. Mojolicious

Mojoliciousのテンプレートヘルパー

テンプレートで利用すると便利なヘルパーについて解説したいと思います。ヘルパーとは、テンプレート内で呼び出すことのできる関数のようなものだと考えてください。layoutヘルパー、stashヘルパーについては、すでに解説していますので、それ以外のヘルパーについて解説します。

スタイルシートの埋め込み

テンプレートの中にスタイルシートを記述したい場合はstylesheetタグヘルパーを使用します。beginendで囲った部分にスタイルシートを書きます。

%= stylesheet begin
  body {
    background:blue;
  }
% end

通常の方法でstyleタグを使って書いてもよいのですが、こちらのほうが簡潔ですし、汎用性のあるタグに展開されるので便利です。以下のようなタグに展開されます。

<style>/*<![CDATA[*/

  body {
    background:blue;
  }

/*]]>*/</style>

またpublicディレクトリにあるスタイルシートをstylesheetタグヘルパーで読み込むことができます。

%= stylesheet '/css/common.css';

これは次のように展開されます。

<link href="/css/common.css" rel="stylesheet" />

タグを挿入できるヘルパーをタグヘルパーといいます。利用可能なタグヘルパーについては「Mojoliciousのタグヘルパーの一覧」をご覧ください。

JavaScriptの埋め込み

テンプレートの中にJavaScriptを記述したい場合はstylesheetヘルパーを使用します。beginendで囲った部分にJavaScriptを書きます。

%= javascript begin
  alert('Hello');
% end

通常の方法でscriptタグを使って書いてもよいのですが、こちらのほうが簡潔ですし、汎用性のあるタグに展開されるので便利です。以下のようなタグに展開されます。

<script>//<![CDATA[

  alert('Hello');

//]]></script>

またpublicディレクトリにあるJavaScriptをjavascriptヘルパーで読み込むことができます。

%= javascript '/js/common.js';

これは次のように展開されます。

<script src="/js/common.js"></script>

アプリケーションオブジェクトの取得

アプリケーションオブジェクトを取得するにはappヘルパーを使用します。

% my $app = app;

コントローラーオブジェクトの取得

テンプレートの中では$selfという名前で、コントローラーオブジェクトを参照することができます。

% my $c = $self

これを使って、テンプレートの中でHTTPメソッドを取得することなどができますね。

% my $http_method = $self->req->method;

データのダンプ

データの内容をダンプするためのdumperメソッドが用意されています。これは機能的にはData::DumperモジュールのDumper関数と同じです。

% warn dumper $date;

他のテンプレートの取り込み

includeヘルパーを使うと他のテンプレートを取り込むことができます。

%= include '/include/header.html.ep

ヘッダやフッタなどは、サイトで共通なことが多いですので、これらを作っておいて、複数のテンプレートから読み込むと便利です。includeヘルパー第二引数以降を利用することで、スタッシュの値を設定することができます。

%= include '/include/header.html.ep, name => 'kimoto', age => 34;

URLの表現

Mojoliciousではアプリケーションの内部的なURLを表現する場合は、パフォーマンスが重要になるアプリケーションを除いてurl_forヘルパーを使用するようにしてください。たとえば「/date/20131215」というURLを表現したい場合は次のように記述します。

<a href="<%= url_for('/date/20131215') %>">2013/12/15</a>

url_forメソッドを使うのは、アプリケーションに汎用性を持たせるためです。このように記述しておけば、CGIとして起動しても、サーバーとして起動しても、URLが汎用的になります。

これは次のように展開されます。

# CGIの場合
<a href="/myapp.cgi/date/20131215">2013/12/15</a>

# サーバーとして起動した場合
<a href="/date/20131215">2013/12/15</a>

Mojo::URLオブジェクト

url_forヘルパーで取得するのはMojo::URLオブジェクトです。Mojo::URLクラスはURLを扱うためのクラスです。

Mojo::URLオブジェクトを文字列化するためにはto_strongメソッドを使うか、文字列として評価します。

% my $url_str = url_for->to_string;
% my $url_str = "" . url_for;

最初の例では「<%= %>」の中は、文字列として評価されるために単純に

<%= url_for('/some') %>

と書くだけで、URLが文字列として展開されます。

現在のURLを取得

url_forヘルパーで引数を指定しなければ、現在のURLを取得することができます。

% my $current_url = url_for

クエリ文字列

url_forヘルパーで注意しておきたいのは、引数なしで現在のURLを取得する場合は、クエリ文字列を除いた部分のURLを取得できるということです。もしクエリ文字列を含めたURLを取得したい場合はurl_withヘルパーを利用します。

<%= url_with %>

たとえば「/some?name=kimoto&age=30」というURLをアクセスした場合はurl_forヘルパーでは「/some」を取得しますがurl_withヘルパーであれば「/some?name=kimoto&age=30」を取得できます。

クエリの部分はMojo::Parametersオブジェクトに保存されています。これはMojo::URLクラスのqueryメソッドで取得できます。

my $query = url_with->query;

またqueryメソッドは、クエリ文字列を設定する機能もあわせてもっています。クエリ文字列を設定するには以下の三種類の方法があります。最初のクエリ文字列が「title=perl&name=ken」だったと想定してください。

クエリ文字列を置き換える

クエリ文字列を置き換えるには次のようにリスト形式で渡します。

$url->query(name => 'taro', price => 1900);

上記の例の場合は以下のように置き換わります。

# 前
title=perl&name=ken

# 後
name=taro&price=1900

クエリ文字列のマージ

クエリ文字列をマージするには配列のリファレンスとして渡します。

$url->query([name => 'taro', price => 1900]);

次のようにマージされます。値が同じものは置き換えられます。

# 前
title=perl&name=ken

# 後
title=perl&name=taro&price=1900

クエリ文字列の追加

クエリ文字列を追加するにはハッシュのリファレンスとして渡します。

$url->query({name => 'taro', price => 1900});

次のように追加されます。

# 前
title=perl&name=ken

# 後
title=perl&name=ken&name=taro&price=1900

Webアプリではページ番号だけを差し替えたいという要望が強いと思います。そういう場合は、クエリのマージの機能を使うのがよいでしょう。

<%= url_with->query([page => $page]) %>

テンプレートヘルパーを利用したサンプル

今回解説したテンプレートヘルパーを使ったサンプルコードを書いてみます。

use Mojolicious::Lite;

get '/person' => sub {
  my $self = shift;
  
  # パラメーター
  my $name = $self->param('name');
  my $age = $self->param('age');
  
  # 描画
  $self->render('index', name => $name, age => $age);
};

app->start;

__DATA__

@@ index.html.ep
<%
  # スタッシュの値
  my $name = stash('name');
  my $age = stash('age');
  
  # ログの取得
  app->log->info('Template Helper');
  
  # HTTPメソッド
  my $http_method = $self->req->method;
  
  # データのダンプ
  my $data = [1, 2, 3];
  warn dumper $data;
%>
<html>
  <head>
    <title>Template Helper</title>
    %= stylesheet '/css/common.css';
    %= javascript '/js/common.js';
  </head>
  <body>
    %= include '/include/header';
    
    Name: <%= $name %><br>
    Age: <%= $age %><br>
    Current URL: <%= url_with %><br>
    Current URL with some change: <%= url_with->query([name => 'ken']) %>
    %= include '/include/footer';
  </body>
</html>

public/css/common.css

CSSファイルを「public」ディレクトリの中に配置しましょう。「public/css/common.css」という名前で保存してください。文字色変更する設定などが書いてあります。

#header h1 {
  color:green;
  border-bottom:1px solid gray;
}

#footer {
  color:red;
  border-top:1px solid gray;
  text-align:center;
}

public/js/common.js

JavaScriptファイルを「public」ディレクトリの中に配置しましょう。「public/js/common.js」という位置においてください。「Hello」と表示するダイアログを実行するJavaScriptです。

alert('Hello');

ヘッダとフッタ

ヘッダとフッタを作ってみましょう。「templates」ディレクトリの中に、「templates/include/header.html.ep」と「templates/include/footer.html.ep」という名前で保存してください。

templates/include/header.html.ep

<div id="header">
<h1>Template Helper</h1>
</div>

templates/include/footer.html.ep

<div id="footer">
Author kimoto
</div>

アプリケーションの実行

このアプリケーションを実行して「/person?name=kimoto&age=32」でアクセスしてみてください。上部にヘッダ、下部フッタが、挿入されています。コンテンツの内容として以下が表示されます。

Name: kimoto
Age: 32
HTTP Method: GET
Current URL: /person?name=kimoto&age=32
Current URL with some change: /person?age=32&name=ken