DjangoのテンプレートエンジンをPHPに移植してみた。

ブラジルのPHP仕事をひさびさにやることになった。
そこで思ったこと。テンプレートエンジンを使いたいよ…
しかも、Djangoみたいに継承ができるやつを。


というわけで、よさげなテンプレートエンジンを探してみようか、
と思ったんだけど、PHPテンプレートエンジン多すぎっす。調べる気失せるっす。


rhacoのテンプレートエンジンはDjango風らしいけど、
テンプレートエンジンだけ使う方法を調べるまで至らなかった…


じゃあ、自分で書いちゃう!?書いちゃう!?

書いちゃった!!
その名もGunyaTemplate。ダサいので名前募集中です。
ブラジル社長によってmumuという名前が授けられました!
(EbiTemplateとかMaitakeTemplateという案も出ましたが、目を逸らしてスルーした)


最初はスクラッチで書いていたけど、
途中でDjangoの実装をモロパクりしだしました。

入手方法

以下のURLから入手できます。

使い方

PHPからは以下のように呼びます。

require_once('mumu.php');
$t = MuParser::parse_from_file('test.tpl');
echo $t->render(array('val1' => 'aaa', 'val2' => 'bbb'));

まず、MuParser::parse_from_file()にテンプレートファイル名を渡します
(MuParser::parse()にテンプレートの文字列そのものを渡してもOK)。
次に、その返り値のrenderメソッドを呼ぶと、渡したPHP連想配列の内容を用いて置換されたテンプレート文字列が返ってきます。
あとは、それをechoするなりしてください。

テンプレートファイルの書き方などは、だいたい以下のドキュメントを参照してください。
ただし、いくつかのタグやフィルタはサポートしていません。

サポートしているタグ/フィルタ/特殊変数

タグ

  • {% include "filename" %} (変数名指定は対応してないです)
  • {% extends "filename" %} (変数名指定は対応してないです)
  • {% block blockname %} {% endblock %}
  • {% for item in items %} {% endfor %} (reversed対応してないです)
  • {% cycle val1,val2 %} (変数名指定して後で参照するのは対応してないです)
  • {% if cond %} {% else %} {% endif %}
  • {% debug %}
  • {% now "format" %}
  • {% filter filter1|filter2 %} {% endfilter %}
  • {# comment #}

フィルタ

  • addslashes
  • length
  • escape
  • stringformat:"format"
  • urlencode
  • linebreaksbr

特殊変数

  • forloop.counter : 現在のループ回数番号 (1 から数えたもの)
  • forloop.counter0 : 現在のループ回数番号 (0 から数えたもの)
  • forloop.revcounter : 末尾から数えたループ回数番号 (1 から数えたもの)
  • forloop.revcounter0 : 末尾から数えたループ回数番号 (0 から数えたもの)
  • forloop.first : 最初のループであれば true になります
  • forloop.last : 最後のループであれば true になります
  • forloop.parentloop : 入れ子のループの場合、一つ上のループを表します
  • block.super : 親テンプレートのblockの中身を取り出す。内容を追加する場合に便利。

現行の問題点

include/extendsなどで相対パスのチェックとかそういうのをサボっているので危険です。
include/extendsなどで無限ループがあるとマズいです。
エラーが激烈不親切です。
エラーハンドリングをサボっているところがあります。
とかいろいろ問題あるよ。

パッチやツッコミ募集中

デバッグろくにしてないので、
問題点あったらツッコミお願いします。
テストスイートも書いてません。


DjangoにあるけどGunyaTemplateで実装してないタグとかフィルタを実装したら、
ここのコメント欄とかいろんな手段で僕に連絡をくれると嬉しいです。


PHPオブジェクト指向のプログラムを書くのが始めてなので、
おかしなことをしている可能性が大です。指摘ください。
オブジェクトを代入したら、オブジェクトの参照が代入されるのかオブジェクト全コピーになるのかとかよく分かってません。