FreeMarker Template Language 入門(6)
パッケージJava製品開発担当の大です。こんにちは。
前回に引き続き、FreeMarker Template Language(以下 FTL)の解説をします。
今回は、マクロに関するお話です。
マクロとは
FreeMarkerにおけるマクロとは、「変数に束縛されたテンプレートのフラグメント(断片)」です。簡単な例をあげましょう:
<#macro greet> こんにちは! </#macro>
ここで定義された変数greet
は、ユーザ定義のディレクティブとして呼び出すことができます。通常のディレクティブと違い、ユーザ定義のディレクティブは先頭に「@
」をつけて呼び出します:
<@greet />
実行すると、こんな風に表示されます:
こんにちは!
マクロは、引数をとることもできます:
<#macro greet user> こんにちは、${user}さん! </#macro>
呼び出しはこんな風になります:
<@greet user="大"/>
実行結果:
こんにちは、大さん!
関数との違い
マクロは、前回出てきた関数とは異なるものです。
関数は値を返さなければなりませんが、マクロは、値を返すことができません。
マクロの本体は、前述のとおり「テンプレートのフラグメント」なので、テキストはそのままテキストとして出力されますが、関数の本体ではテキスト出力があっても無視されます。
関数呼び出しは式を書ける場所ならどこでもできますが、マクロ呼び出しはFTLタグを書ける場所でしかできません。
たとえば、上で定義したgreet
マクロぐらいの内容なら、関数として定義、使用することも可能でしょう。
<#function greet user> <#return "こんにちは、${user}さん!"> </#function>
${greet("大")}
しかし、以下のようににちょっと複雑な出力をするなら、マクロでやるほうが関数でやるより便利です(関数でもやれないことはありませんが。。)。
<#macro table cols rows> <table> <#list 1..rows as row> <tr> <#list 1..cols as col> <td>${row}, ${col}</td> </#list> </tr> </#list> </table> </#macro>
<@table cols=3 rows=2 />
<table> <tr> <td>1, 1</td> <td>1, 2</td> <td>1, 3</td> </tr> <tr> <td>2, 1</td> <td>2, 2</td> <td>2, 3</td> </tr> </table>
return
ディレクティブ
マクロ中でもreturn
ディレクティブを使用できます。が、前述のとおり値を返すことはできません。処理をそこで終了するというだけです。
<#macro hoge> ここは表示されます。 <#return> ここは表示されません。 </#macro>
nested
ディレクティブ
nested
ディレクティブは、マクロ呼び出し時に渡されたテンプレートのフラグメントをマクロ中から呼び出します。Rubyをご存知でしたら、yield
みたいなものと考えればわかりやすいでしょう。nested
を利用すれば、マクロをより汎用的に定義することができます。たとえば、リストを引数にとり、その要素をnested
呼び出しに使用するマクロを考えます。
<#macro lprint lst> <#list lst as item> ・${item}<#nested item /> </#list> </#macro>
このマクロを、
<@lprint 1..3; x>^2 = ${x * x}</@lprint>
のように呼び出せば、
・1^2 = 1 ・2^2 = 4 ・3^2 = 9
このように表示されます。また、
<@lprint 1..3; x>^3 = ${x * x * x}</@lprint>
と違うフラグメントを渡せば、
・1^3 = 1 ・2^3 = 8 ・3^3 = 27
違う出力が得られます。
<@lprint ["Let's go", "to the", "land of Medetai"] />
nested
呼び出しするものがなければ、何も行われません。
・Let's go ・to the ・land of Medetai