あんまりやりたくなかったのだが、Windows2003Server上のIIS+PHP5+Smarty環境で開発を行う必要に迫られた。
 この環境を構築するのは初めてだったが、予想よりかはあっさりと動き開発を始めた・・・のだが、なんかSmartyテンプレートのヘンなトコロで以下のよーなエラーが発生。

Fatal error: Smarty error: [in index_01.tpl line 2]: syntax error: unrecognized tag: 〜

 認識されないタグ?でも指定された行は単なるテキストで、Smarty関連のタグは入ってない。こーゆー時ってヘンなトコロにヘンな文字コードが入って誤認識を起こしてる事が多いよなーとか思い、入力されてる文字列を1つ1つ確認していったところ、「ボ」でエラーを起こしてることを突き止めた。でも今までSmarty使ってても「ボ」ってフツーに使ってたよなー。

 結局のところコレはShift-JISにおける「ボ」の文字コードが「837B」であり、 Smartyのタグ記述用デリミタ「{」の文字コード「7B」とカブってる事が原因らしい。そっかー、今までSmartyってEUC-JPかUTF-8でしか書いたことなかったからなー。Smartyってマルチバイト環境の事あんま考えて無さそうだし、やっぱ慣れない事はするべきじゃないってことですかねえ。

 で、上記の対抗策として、デリミタを無効化・画面表示する{literal}で該当文字列を括るとか、EUC-JP等で記述して mb_convert_encodingで変換する手とかがあるようだが、文字列をPHP側で変数に入れてソレを表示する分には問題ないっぽい。状況にもよるだろうけど文字列は全て変数に叩き込むのも1つの手かも知れない。

追記:「本」もダメだった。他にもいくらでもありそう。さすがに文字コード全部見る気はしない。文字列全て{literal}で括るのが基本になるでしょか。
 当然だけど括った中はSmartyのタグも無効化されるので書く位置には注意。

2006-05-31 [技術・作業]

 まあマニュアル読めば分かる話ではあるのですが。

 強力なPHPテンプレートエンジン「Smarty」。従来html埋め込み型のスクリプトであるPHPで、いわゆるMVCを行いたいとした場合に非常に有効な機能と言うかツールである事はあちこちのサイトやら書籍やらで述べられてる通り。
 私はつい最近まで独自に記述したテンプレート(もどき)ファイルをメインのPHPからincludeすることでなんちゃってMVCを実行していたのですが、取り込んだファイルも結局はPHPファイルでしかないので分解点はヒジョーに曖昧なモノであり、機能の追加や改修を進めるにつれ結局どこで変数生成してるんだか分かんなくなる事が多かったというより常でした(苦笑)。
 それでも「べーつにテンプレートエンジンなんて使ったって考えること増やすだけでそれほど効果があるとは思えないねえ」とか思ってSmartyにはずーっと手を出していなかったのですが、ちょっと仕事でSmartyに関わる必要が発生したため、「じゃあとりあえず一度把握しとくか」と、まずは本サイトの改修時にSmartyを導入したのが 2005年の12月頃。

 ・・・正直すまんかった(笑)。いやマジいいわコレ。今までごっちゃになりがちだったMC部分とV部分が実にすっきりと分離でき、その後の機能追加や画面変更がめっちゃ楽になった&論理的に把握出来るようになりました。結果として実現可能な手法も増え、 Smartyを把握するのに係った手間を考えてもどう見てもプラスです。ありがとうございました。

 ただ、役割をはっきり分担すると言うことはある意味ムダな処理が発生する余地を生むのもまた事実。単体のPHPを考えた時に、例えばあるループである演算をしながら動的に表示を行っていた場合、コレをPHPとSmartyで実現しようとすると、まずMC部であるPHPで表示すべき結果の演算のループを予め済ませておき、改めてSmartyでループを回して表示する、といった二度手間が内部的には発生していると思われます。まあ後者は基本的に表示するだけのループだしキャッシュやらなにやらで体感的な速度差は感じないハズですが。

 で、そう考えるとSmartyのテンプレート側で某かのPHPスクリプトを実行したくなる。でもSmartyテンプレートで実行できるのはSmartyで独自に定義された関数だけで自由にPHPスクリプトを組む事は出来ない。・・・基本的にはね(※php_includeを除く)。

 ここでよーやく話は「独自関数」と「独自修飾子」の話になるわけで。Smartyは某かの処理を行う関数と、変数にパイプでつなげる事で変数に対し某かの編集を加える修飾子をいくつか標準で持っていますが、コレをプラグインとして独自に作成することができます。

 手法としては割と単純で、plugins_dirで指定されるフォルダ内に関数を記述したファイルを作るだけ。ただファイル名とfunctionの記述方法だけは決まっており、関数の場合ファイル名を

function.[独自関数名].php

とし、中で記述するfunction名を

smarty_function_[独自関数名](){~}

とします。なおここでの[独自関数名]は同じにする必要アリなので注意。修飾子の場合ファイル名を

modifier.[独自修飾子名].php

関数名を

smarty_modifier_[独自修飾子名](){~}

とする、と。なお関数の中身は極フツーに自分の処理したいPHPの関数を書けばOK。後はSmartyのテンプレートの中で、標準関数や修飾子を使うように

{[独自関数名] XXX=[変数とか]}
{[変数とか]|[独自修飾子名]}

とか書けば使えます。

 ただ、この方法で独自関数を加えられるとしても、MCV分離という本来の目的から言えば余り多用すべきでないので、頻繁に出てきて且つデータ量が多い(PHP側で処理してから渡されると時間がかかるモノ)とかメインのシステムとはほぼ切り離されてるよーな処理系とかに、ほんのちょっと使うのが良いかと思われ。このサイトで言うとトップページ・ブログ部の「表示日選択用カレンダー」の日付処理と整形部を独自関数とし、ブログデータの配列を渡す事でカレンダーを生成するようにしてます。他にもつまんない事で3~4つの独自関数&修飾子を使ってます。設計段階でMCVを想定していなかったがために作ってしまったモノなので、今後は設計段階からMCVを考慮し、データの演算系は極力PHP側だけで完結させたいと祈ってます。祈ってどうする。

関連タグ:Smarty
2006-02-07 [技術・作業]