FreeMarkerおぼえがき

大昔にテンプレートエンジンのFreeMarkerに関する記事書いてそれ以降書いてなかったので久々に。
FreeMarkerって全然日本語のドキュメントないんですよね。こまりますよね。
覚書程度にちょっとまとめてみます。
引きの無いタイトルなのは需要なさそうな上に自信もないからです。へへへ!うへへへ!

変数の存在有無を確認したい!

「??」とか「?has_content」とか「?if_exists」とかあるけどどれ使えばいいのよ!
FreeMarker Manual - List of deprecated built-ins
「?if_exists」とかはdeprecatedになってます。
ちょいちょい使ってくる人いるのでなんかその度指摘してる気がします。動きますけどね。
じゃあ「??」と「?has_content」はどう使い分けるのよ!ということでちょっと動きをみてみます。


テストのために以下のようなコードを書いておきます。

<#if test??>
[??]true
<#else>
[??]false
</#if>
<br/>
<#if test?has_content>
[has_content]true
<#else>
[has_content]false
</#if>


この状態でtest変数の状態を変えてテストしてみます。

testがそもそも存在しない場合
[??]false 
[has_content]false 

両方falseになりました。

testが空文字の場合

予めassignしときます。

<#assign test = ""/>


テスト。

[??]true 
[has_content]false 

「??」のほうがtrueになりました。

testがサイズ0の配列の場合

さっきと同じように予めassignしときます。

<#assign test = []/>


テスト。

[??]true 
[has_content]false 

空文字と同じ結果になりました。
つまり、


「??」は変数が存在すればtrueを返し、「?has_content」は変数が存在してかつ中身が空でないときにtrueを返してくれるみたいです。


「?has_content」と結婚したい。


あとtestがbeanだったとして、その中にhogeってフィールドがあったとき、

<#if test.hoge??>

とか

<#if test.hoge?has_content>

とか書きたいところですが、こうするとtestが存在しないときエラー吐くので、

<#if (test.hoge)?has_content>

こんな感じで書いてやると仮にtestが存在しなくてもエラー吐きません。すてきね。

変数の存在有無確認、かつあった場合は特定の値に一致するか確認したい!

こんな感じのコードをよく見ます。

<#if hoge?has_content && hoge == "1">

けどもっとシンプルにこれでも望んだ挙動をします。らくちん。

<#if hoge! == "1">


ただbooleanだとちょっと動きが怪しい。
何も考えないで上を踏襲した感じにすると

<#if hoge!false == true>

こう書きたいところ…!
だけどこれだと仮にhogeが存在してかつ中身がtrueの場合に全てtrueになる。
同じく中身がfalseだと全てfalseになる。ので!

<#if (hoge!false) == true>

こうすると望んだ挙動になるっぽい。先に右辺が判定されてごにょごにょ的な感じなんだろうか。

存在する場合は出すかつ適当なbuilt-inも実行したい!

たとえばpostDatetimeみたいなDate型を保持した変数があって、こいつがftlにきた時点で存在する場合もしない場合もあるとして、あった場合は適当なフォーマットで表示したい場合を考えてみます。
ふつーにやると

<#if postDatetime?has_content>
${postDatetime?date}
</#if>

とかですが、以下のようにシンプルにも書けます。

${(postDatetime?date)!}

らくちん!行数も少ない!うれしい!
特定のタグで囲いたいとかの場合は結局if書かないといけないんですけど。
html構成は変えずに代替テキスト表示とかなら以下のようにも書けるので使いどころはあるかなーと思います。

${(postDatetime?date)!'ひづけないよ!'}

リクエストパラメータの値を取得したい!

あんまり使ったことありませんが…。
以下のようなURLがあったとして、

http://d.hatena.ne.jp/tm8r/?test=hoge

「test」パラメータの値を取得したいときは以下のように記述すれば取得できます。

${RequestParameters.test}

こんな書き方でもいけます。

${RequestParameters['test']}

リクエストスコープの値を取得したい!

リクエストパラメータとあんまり変わりません。こっちはたまに使うやも。
request.setAttribute("test","hoge")とかやった場合、以下のように記述すれば取得できます。

${Request.test}

リクエストパラメータと同様にこんな書き方でも。

${Request['test']}

数値比較したい!

大したあれじゃないですけど…
数値比較するとき

<#if num > 1>
true.
</#if>

こうしたいところですが、これだとftlの終了文字と被ってエラー吐くので

<#if (num > 1)>
true.
</#if>

えいやーっとやってもいいんですけど、なんかめんどくさいので別の書き方したい。

<#if num gt 1>
true.
</#if>

ので僕はこう書きます。
右辺を含む場合はgteで。詳細は以下。
FreeMarker Manual - Expressions

FreeMarkerで出来ることをしりたい!

まあドキュメント見ろって話なんですけど…ど…。
FreeMarker Manual
インデックスは↑なんですが、僕は英語わかんない残念な人なのでこのインデックス見てもどこいけばいいか分かりません。
ので、アルファベット別のインデックスを見ます!
FreeMarker Manual - Alphabetical Index
なんかリスト系調べたいなーってときはlistで検索して、エスケープとかしたいなーと思ったらescapeとか残念な英語力でも想像しうる単語で検索できるので地味に便利です。
FreeMarker初めて使う人にはとりあえずここぶん投げます。使いやすいと思うの僕だけだったらすみません。しにます。

おわり

自分がたまに忘れたりする部分とか周りがよくハマりがちな部分とか思いつくものを書いてみました。
他にも何かあったらまた書こう。主に自分のために。
どうでもいいんですけど普段ftlって言うのでFreeMarkerってすごい違和感ある。Velocityはvmって言わないのに。ふしぎ!

スポンサーリンク