Template Toolkit 社内勉強会のレポート
あちこち間違ってるという指摘を受けたのであちこち直しました><
にぽたんさんによる、Template Toolkit(TT)の社内勉強会がありました。 という訳でOpen & Share!
アジェンダ
- 変数展開について
- オブジェクトからの呼び出し
- 意外と知られてない事
- 質問への回答
変数展開について
TTはPerlなので、Perlに準拠する。
Perlは$とか@(シギル)で変数の型がわかるけど、TTにはそういうのがない。 しかし、型自体は持っている。
- スカラー
- 配列
- ハッシュ
- オブジェクト
実際は複雑で、スカラーのなかに配列とかなんか色々あるらしい。
スカラー
実は業務ではあんまり使われない。 単一の値しか持たない文字列。 または数値。
配列
一つの変数の中に複数の値を持つ値
ちなみにコード中に登場する "=" と "in" に違いはない。 全く同じ動作をする。
ちなみにFOREACH中に登場する "=" と "in" に違いはない。 全く同じ動作をする。
ハッシュ
keyとvalueのペアの組み合わせを持つ変数。 順番という概念がない。
オブジェクト
実際の業務では最も使う事が多い。
Perlのソースコードでセットされる。
Perlのオブジェクトは、多くは高機能なハッシュ。 ハッシュに色んな機能を授けたものをオブジェクトと呼んでたり。 まあでも、必ずハッシュってわけじゃない。 ハッシュ的な使い方ができる別のもの、みたいな。
メソッド
[% IF article.is(hogehoge) %] ←こんな風に引数がある場合は確実にオブジェクト
一見するとハッシュぽいけど、実はDBからデータを引いてくるオブジェクト(メソッド)もある
[% article.id %] ←実はDBから引いてる [% article.owner.nickname %] ←ここだけ見ても、メソッドなのかハッシュなのかは分からない
オブジェクトからの呼び出し
ハッシュ要素を持つオブジェクトは、同名のkey展開もメソッド呼び出しもできる場合がある。
例えば[% foo.bar %]で、bar が値とメソッドの両方で使われている場合(名前の重複)、メソッドが優先される。
意図的にハッシュを優先するには、item()メソッドを使う。
[% foo.bar #method %] [% foo.item('bar') #hash %] [% foo.item(3) #array %] ←配列形式でも呼び出せる
違う書き方にfoo.$num とかもあるけど、きもかったらitem()で。
あと、PGが設計ミスをして item っていうメソッドを定義しちゃってたら打つ手が無い。
意外と知られてない事
テンプレートを構成する要素
- Directive
- VMethod
- Filter
Directive
大文字で書いてるやつ。 命令。
[% INCLUDES %] [% IF hogehoge %]
ちなみにアパッチとかの命令も大文字。これもDirective.
TTは変数名を大文字にするとDirectiveと解釈する事があるので注意。
VMethod
Vはバーチャルの意味。 変数の後からドットで繋がれているメソッド。
[% IF array.size > 0 %] [% hoge.item() %] [% IF foo.match('-') %]
配列とかスカラーに必ず使えるメソッドをVMethodという
Filter
文字列に対してのフィルタリングを行う。 文字列の後からパイプで繋ぐ。
結構簡単に作れるので、案件ごとに作ってる物が存在する。
TT標準のフィルターもある。
[% hoge | html %] [% hoge.truncate(10) %]
など。
uriフィルタはquery stringに変換してくれて便利。 だけど、TTのバージョンが2.16以降じゃないと使えない。
Directiveの紹介
DEFAULT
このDirectiveが登場した時点で、その変数の値が0または未定義だった場合に適用される
[% DEFAULT foo = '123' %] [% foo %]
変数fooの中身が0かそもそも未定義だったら、fooに文字列123が代入されてそれを出力する。
UNLESS
IFの逆。ややこしいので、最初はUNLESSは無視して考えると良い。 最後に反転する。
UNLESSのorは絶対に通る。間違ってやっちゃわないように注意。
SWITCH / CASE
条件分岐が複雑な場合に使う。 ただしイコール判定がしかできない。
[% SWITCH 'foo' %] [% CASE foo %] ←fooなら hoge [% CASE ['fooo', 'foooo'] %] ←foooかfoooo hogehoge [% CASE %] ←どれにも適合しなければ orz [% END %]
ちなみにIF ELSEとの使い分けは、書く人の好みだったり。
META
[% META title = 'foo' text = 'hoge' %]
みたいに定義すると、そのテンプレート内で使える。 使う際はtemplate変数で使う。
[% template.title %]
わざわざMETAとtemplate変数を使う理由
絶対に汚染されない変数だから。 予約されている。
予約されているのは他にもある。
- template
- compornent
- loop
- error
- content
あと、Ver,2.19以前は tags が使えないバグがある。
loop
FOREACHとかWHILEの中で自動で設定される変数。 VMethod.
[% loop.last %] [% loop.size %] [% loop.count %]
など。
PROCESS
変数のスコープがグローバル。 全ての変数の値が上書きされる。
つまり、インクルードされるファイル側の変数がhtmlファイル側でも使える。
INCLUDE
変数のスコープがレキシカル。 参照はできるが、上書きはしない。
つまり、インクルードされるファイルの変数はhtmlファイル側では使えない
こっちのがまあ安全。
INSERT
そのまんま出す。 速度は一番速い。
TTの構文を解釈しない。
また、PROCESSやINCLUDEは、BLOCKの実行をする場合にも使う
Q&Aコーナー
Q viewの、とあるテンプレで使える変数を知るには、MとかC側のファイルを見るしかないですか?
A Yes.
Q 処理が重くなるテンプレート側の書き方ってありますか?
A 基本的にはシステム側のが影響が大きいけど、DBを引いてくるメソッドを何度も書くとロスはでる。 キャッシュ化すると良い。
Q テンプレートをさわる人に知っておいてほしいルールとかありますか?
A ユーザが入力できる内容を出力する変数にはhtmlフィルタを付ける事。 セキュリティホールになるので。