モバゲータウンのノウハウ満載! フレームワークMobaSiFを使おう!

第5回テンプレートエンジンMTemplate

前回はMobaSiFに含まれる個々のPerlモジュールを解説しました。今回は、MobaSiFに含まれるテンプレートエンジンMTemplateについて説明します。

テンプレートエンジンMTemplate

MobaSiFに付属するテンプレートエンジンMTemplateは、次のような特徴を持ちます。

1つのテンプレートファイルで3キャリアに対応

1つのテンプレートファイルを記述するだけで、3キャリアに対応できます。また、キャリアごとに表示する内容を変えることもできます。

事前コンパイルにてバイナリテンプレート生成

HTTPリクエストを受け付けるたびにテンプレートをparseするのは非効率と考え、事前コンパイルによりバイナリテンプレートを生成する方式をとっています。

mmapによる共有メモリの利用

DeNAのサービスで長く使われているFastCGIでは、プロセス上のメモリキャッシュを利用するとアプリケーションプロセスごとにメモリが利用されてしまい非効率です。そこで、UNIX系のシステムコールであるmmap( )を使い、ファイルをメモリにマップして各アプリケーションプロセスから共通のメモリ領域を利用できるようにしています。

XSによる高速処理

主要部分がC言語で実装されているため処理が高速です。

MTemplateの利用の流れ

(1)テンプレートファイルの作成

テンプレートファイルはtemplate/_system以下に.htmlという拡張子を付けて置きます。文字コードはShift-JISを利用します。テンプレートファイルで利用できる独自タグなどについては後述します。

(2)テンプレートファイルのコンパイル

script/tool/compile_templateコマンドを実行すると、templateディレクトリ以下のテンプレートファイルのうち、前回のコンパイル以後に変更のあったファイルがすべてコンパイルされます。コンパイル結果はdata/html_binディレクトリに出力されます。

Webサーバ(Webアプリケーション)が起動している場合でもコンパイルされたテンプレートは即時に反映されるので、再起動は不要です。

(3)Webアプリケーションロジック(.pmファイル)から呼び出す

リスト11は、Webアプリケーションロジックからテンプレートを利用する例です。MTemplate::
insert( )の第1引数はテンプレートファイル名で、template/_systemからの相対パスで記述し、拡張子.htmlは省略します。たとえば上記の利用例では、template/_system/regist/test.htmlが利用されます。

リスト11 Webアプリケーションロジックからテンプレートを利用する
use MTemplate;
my $html = MTemplate::insert("regist/test", $rhData);
Common::output(¥$html);

第2引数は、変数展開や条件分岐に利用されるハッシュリファレンスです。詳しい利用の仕方については次項「テンプレートファイルの記述方法」とともに説明します。

テンプレートファイルの記述方法

MTemplateのテンプレートファイル独自の記述は「$」「$」の間で行います。あるいは「$で囲まれたタグを利用します」という表現が正しいかもしれません。以下、具体的な記述方法を説明します。

変数展開

リスト12は、テンプレートファイルでの変数展開の記述例です。NAMEはMTemplate::insert( )の第2引数に与えたハッシュリファレンスのキーに対応します。たとえば$rhData->{text}にセットした値によって、$b:=text$が置き換えられます。また、オプションについては表4にまとめました。

リスト12 変数展開の記述例
$=OPTIONS:NAME$
表4 MTemplateで使用するオプション
表記機能詳細
hHTML特殊文字変換下記のような変換を行う。クロスサイトスクリプティングなどへの対策のため、hオプションは常に付けるのが原則
" => "
< => <
> => >
& => &
hn改行コード変換hの処理に加え「\n」「<br />」に変換する
eurl escapeURLに含めてはならない文字をエスケープする(例:半角スペースを%20に変換)
bbypass無変換

条件分岐

条件分岐のときの記述はリスト13のようになります。これらの条件分岐はネスト({ }の間にさらにif文を書くなど)も可能です。

条件文CONDには表5の形式が利用できます。左辺値の変数は、変数展開と同様、ハッシュリファレンスのキーを記述します。右辺値は定数のみ利用できます。また、変数の値が0のとき表5の★印の場合は、Perlの一般的な動作と異なる点にも注意が必要です。

リスト13 条件分岐の記述例
$ if (COND) { $
$ } elsif (COND1 || COND2) { $
$ } elsif (COND1 && COND2) { $
$ } else { $
$ } $
表5 CONDの形式
はたらき
変数=定数文字列比較
変数!=定数文字列比較
変数ne '' ★(空文字との比較なので、変数="0"の場合はTRUE)
!変数eq '' ★(空文字との比較なので、変数="0"の場合はFALSE)
変数>=定数数値比較
変数>定数数値比較
変数<=定数数値比較
変数<定数数値比較

ループ

ループはリスト14の形式になります。ループの中にループを記述することもできます。

リスト14 テンプレートファイル中のループ記述例
$ loop (NAME) { $
$ } $

たとえば、前述の$rhDataについてリスト15のようにハッシュリファレンスを要素に持つリストのリファレンスをセットし、テンプレートファイルにはリスト16のような記述を行うと、出力は図2のようになります。つまり、リストの各要素のハッシュリファレンスに関して変数展開が行われながら繰り返し処理がされるということです。

リスト15 ループに渡すリストの定義例
my @fruits = ( {name => 'apple', price => '100'},
{name => 'orange', price => '120'},
{name => 'melon', price => '500'},
);
$rhData->{List} = \@fruits;
リスト16 リストの各要素を表示するテンプレートファイル例
$ loop (List) { $
$=h:name$ は $=h:price$ 円! 
$ } $
図2 実行結果
apple は 100 円! <br>
orange は 120 円! <br>
melon は 500 円! <br>

共通要素の読み込み

先述した変数展開や制御構造以外に、テンプレートで共通的に利用される要素を読み込む機能がありますリスト17⁠。上から順に利用例を解説します。

リスト17 共通要素の読み込み
$INC:NAME$
$CON:NAME$
$STY:NAME$
$INC:NAME$…template/_inc_html.txtの内容をインクルード

テンプレートファイルに$INC:header$と記述すると、template/_inc_html.txtファイルの$INCDEF:header$と$/INCDEF$で囲まれた部分が挿入されます。

$CON:NAME$…template/_const.txtの定数定義を使用

template/_const.txtファイルに「title : MobaSiF」と書かれている場合、テンプレートファイルに$CON: title$と記述すると、MobaSiFに置換されます。

$STY:NAME$…template/_style.txtのスタイル定義を使用

template/_style.txtファイルにリスト18のような記載があるとします。

リスト18 スタイル定義の例
default {
    attr-body:
    color-disable: #999999
    color-base: #ff6633
}
その場合、
<div style="backgroud-color:$STY:color-base$">

<div style="backgroud-color:"#ff6633">

となります。

キャリア単位の出し分け

接続元のキャリアによる表示の出し分けは、リスト19のタグを利用します。DOMAINSは小文字のd(NTTドコモ)、a(au⁠⁠、v(ソフトバンクモバイル)で指定し、複数ある場合はカンマ(,)で区切りますリスト20⁠。

リスト19 接続元キャリアによる出し分け表示の記述方法
$DOM:DOMAINS$
特定のキャリアからの接続時のみ表示する部分
$/DOM$
リスト20 リスト19による記述例
$DOM:d,v$
ドコモとソフトバンクモバイルの端末のみ表示
$/DOM$

その他の機能

$ENC:STRING$

文字列STRINGをURLエスケープします。URL中に日本語を入れる場合などに便利ですリスト21⁠。

::TIME(YYYY/[M]M/[D]D [H]H:II)

unixtimestampの数値に変換され、主にif分の定数部分に利用されますリスト22⁠。

リスト21 $ENC:STRING$の利用例
<a href="_search?query=$ENC:キーワード$">
リスト22 ::TIME( )の利用例
$ if (CurrentTime >= ::TIME(2005/9/16 18:00) { $

サンプルアプリケーションの紹介

MobaSiFには、別途サンプルアプリケーションが用意されており(本稿執筆時のファイル名はmoba-0.9.0-sample-1.0.tar.gz⁠⁠、会員登録機能や日記の入力・一覧・コメント機能などが含まれています。インストール・設定後はトップページ(サーバのドメイン名がexample.comであればhttp://example.com/)からたどることで動作を確認できるようになっており、またconf/pages.confファイルにページの登録があります。このサンプルアプリケーションを参考にすると、MobaSiFからDBを利用する方法も理解していただけると思います。ぜひ参考にしてください。

おわりに

本特集では、MobaSiFのメリットと利用方法を説明してきました。MobaSiFを利用するとケータイ向けサイトを簡単に開発できると思いますので、ぜひ利用してみてください。また、モバゲータウンのような大規模ケータイサイトのフレームワークがどのようになっているか覗いてみるという楽しみもあると思います。

MobaSiFにはここで取り上げた以外の機能もありますが、本稿では主にケータイ向けWebアプリケーションに特化した機能に焦点をあてて解説しました。ほかの機能に関する情報や、最新の情報などはMobaSiFのdocsフォルダ内ドキュメントにも含まれており、また本稿の訂正情報も含め下記サイトでもお伝えしていく予定です。

SourceForge.jp上のプロジェクトページ
URL:http://sourceforge.jp/projects/moba/
DeNA技師のメモ
URL:http://d.hatena.ne.jp/tokiharu/

おすすめ記事

記事・ニュース一覧