Smarty修飾子にハマり
2006/02/14 23:57
SmartyでXHTMLテンプレートにアサインする際に、EUC-JPの文字列をUTF-8に変換する必要がある。
この変換を以前はmojaviビューにやらせてたけど、Smarty側に修飾子プラグインとして実装したほうが良いとわかり、以下はその変更の経緯を書いたメモ。
↓これは、修飾子(...を要約したもの)の最初のバージョン。
function smarty_modifier_encoding ($value) {
return mb_convert_encoding($value, 'utf8', 'euc-jp');
}
この単純なコードだと、配列をアサインしたときにうまくいかない。つまり、mb_convert_encodingがエラーを返す。世の中そんなに甘くない。
# というか、Smarty標準のescape修飾子も、配列に対して使うとエラーになる様な
# 気がするんですが。仕様ですか?
↓この点を修正してみたバージョンが、これ。配列の問題を解決。
function smarty_modifier_encoding ($value) {
if (is_array($value)) {
return $value;
}
return mb_convert_encoding($value, 'utf8', 'euc-jp');
}
配列がアサインされたときは、アサイン値をそのまま返すことにする。
foreachブロックの中で、配列の各要素がアサインされた時にmb_convert_encodingが実行されるので、このコーディングでも問題はない。
解決したと思ったら、次の問題が出てきた。
↓テンプレートでは以下の様に、foreachタグを使ったループを書いているとしよう。
{foreach from=$entries item=entry}
<a href="/?module={$module}&action=Detail&entry={$entry.id}">{$entry.id}</a>
{foreachelse}
該当するエントリーがありません。
{/foreach}
ここで、entries値に何もアサインしない場合にforeachelseが評価されず、何故かループを1回廻してしまう。明示的に、nullや空文字列('')や空配列(array())等をアサインしてみたがダメ。結果は変わらず。
↓今のままでも、テンプレートをこんな風に変えてみると動くけど、かなりショボい。
{if $entries}
{foreach from=$entries item=entry}
<a href="/?module={$module}&action=Detail&entry={$entry.id}">{$entry.id}</a>
{/foreach}
{else}
該当するエントリーがありません。
{/if}
仕方がなくて、Smartyのソースやら生成されたキャッシュやらを読んでみたら、アサインされた値が空の場合にもmb_convert_encodingが実行されてしまうのが問題の様だ。よって、
function smarty_modifier_encoding ($value) {
if (is_array($value)) {
return $value;
} else if ($value) {
return mb_convert_encoding($value, 'utf8', 'euc-jp');
}
}
てな具合に書き換えれば良いことになる。
$valueが空の場合に修飾子はnullを返し、mb_convert_encodingは実行されない。
これでバッチリ、今のところ問題なし。
これだけのことにえらく手間取ってしまったけど、Smartyのソースを読む良い機会だったから、よしとする。
