テンプレート内での文字列の連結

2008/04/22 | Smarty

Smartyテンプレート内で、変数に格納された文字列の結合をしたい場合がある(つまり「変数を結合したい」のだが)。

単に文字列を結合するだけならcat修飾子でいい。
{$str1|cat:’_add’}とか{$str1|cat:$str2}とか

結合した文字列を他の処理で使いまわしたいということはないだろうか。たとえば上記の処理で得られる文字列をキーとした配列中の値を取得したいとか・・・。
そんなときにはassign関数が使えるのだが、たいていの場合は期待通りの動作をしてくれない。しかし記述方法ひとつで、しっかりと動作してくれる。それは「バッククォート(`)」だ。

例えば変数$str1と$str2を結合した$strを作りたいときはこんな具合に記述する。

{assign var=str value=”`$str1“$str2`”}

仮に$str1=’abc’、$str2=’def’だとしたら、$strは’abcdef’になる。
こういうの、マニュアルに書いてあればいいのに。

テンプレート内での分割処理

2008/04/21 | Smarty

テンプレートエンジンSmartyで、割り当てられた変数(配列)を分割するための関数を作ったのでメモ。

例えばリンク集(バナーで表示)を作るって表形式で表示したい場合、表の列数によってテンプレート内で「行の開始かどうか(<tr>タグを出力するかどうか)」「行の終了かどうか(</tr>タグを出力するかどうか)」といったロジックを書くことになる。テンプレート内でのロジックは減らしたいので、上記のように書くのはあまり好きではない。

PHPには便利な関数array_chunkというのがある。配列を指定した個数の配列に分割してくれるというものだ。さらに便利な関数でarray_padというのがある。指定個数に満たない配列を、指定した値で満たしてくれる関数だ。

一番簡単なのはコントローラ(もしくはメイン処理)で、上記の処理を入れることだが、表示を変更したい(例えば表の列数を増減したい)場合は、コントローラのプログラムを変更しなければならず、本来表示側だけで対応したいのに、本末転倒となるわけだ。

んで、Smartyの関数を作って、テンプレート内で分割できるようにした。関数はfunction.array_split.phpという名前で、以下の内容で、しかるべき場所に保存。

<?php
  function smarty_function_array_split($params, &$smarty)
  {
    $paramKey  =$params[‘var’];
    $paramValue  =$params[‘value’];
    if(is_null($paramValue)){
      $paramValue=array();
    }
    $paramSplit  =$params[‘split’];
    
    if($paramValue){
      $paramSplitted=array_chunk($paramValue,$paramSplit,true);
      $lastValue=array_pop($paramSplitted);
      $lastValue=array_pad($lastValue,$paramSplit,NULL);
      array_push($paramSplitted,$lastValue);
    }else{
      $paramSplitted=array();
    }
    $smarty->assign($paramKey,$paramSplitted);
  }

もうちょっとエラー処理を入れなくてはいけないけれど・・・。
もっと早くに関数作ればよかったな。

ADODBのsqliteドライバ

2008/04/08 | ADODB

現在簡単なウェブアプリを書く際は、フレームワークとしてguesswork、データベース接続にADODB、テンプレートエンジンはSmarty(もしくはPHP直接記述)という組み合わせを使い、データベースにMySQL(最近はSQLiteも)を使用することがほとんどだ。この組み合わせの中でADODBとSQLiteを使用した際に発生した問題についてメモ。
ADODBでは他のデータベースライブラリと同様に、使用するデータベースを定義することによって必要な処理が分岐されるようになっている。例えばPostgrSQLを使用する場合はpostgres、MySQLを使用する場合はmysqlといった具合だ(文字列の指定方法はデータベースライブラリによって違うので注意が必要)。ADODBでSQLiteを使う場合はドライバに2種類あり、それらは「sqlite」と「sqlitepo」だ。最初はその違いを把握せず(マニュアルなど読んでいない)、「sqlite」を使用していたが、あるとき不具合が出てしまった。

MySQLの場合は例えばselect文を投げてデータを取得した場合は以下のような配列で取得できる。

$row[‘id’]
$row[‘name’]

もちろんSQLiteでも基本的には上記のように返してくれる。しかし例えば複数のテーブルを結合したりしたselect文を発行したりすると、MySQLの場合は上記と同様に返してくれるのだが、SQLiteの場合はテーブル名をくっつけて返してしまうのだ。

$row[‘user.id’]
$row[‘user.name’]

こんな具合だ。「え〜これでは互換性が保てない・・・」と思ってよくよくマニュアルを読んでみた。そしてドライバの違いに気づいた。マニュアルによると、


移植性のあるSQLiteドライバ。sqliteでは他のドライバのように連想モードが機能しないため。つまり、複数テーブルを選択(結合)すると、テーブル名が”sqlite”ドライバの連想キーに含まれます。
“sqlitepo”ドライバでは、テーブル名は返されたカラム名から取り除かれます。この結果が衝突したとき、最初のフィールドが優先されます。

そういうことだったのね。互換性(移植性)を重視するなら「sqlitepo」を使用しなさい、と。しかしこれではどんなデータベースでも汎用的に利用できるライブラリという意味合いがなくなってしまっているような感が無きにしも非ず・・・。気を取り直して「sqlitepo」を使用することにした。

SmartyのPOSTフィルターが適用されない

2008/01/20 | Smarty

SmartyはPHPで一番メジャーなテンプレートエンジンということもあり、各種フレームワークと組み合わせて使うことも多い。しかし時折、うまく動かないこともある。
今回遭遇した問題は「SmartyのPOSTフィルターが動作しない」ということ。

Smartyはその処理の前後で、フィルター処理をかけることができる。たとえば文字コードを変換するとか、特定の文字列を置換するとか・・・。便利な機能だ。
とあるフレームワークを使っていて、上記の問題が発生した。POSTフィルターは動作しないがPREフィルターは動作するのだ。なぜ???。

結論として、これはフレームワークを併用して使用していることが原因だった。では、その理由は何か?。

フレームワークでは、通常Smartyを、Smartyの正規の手順にそって呼び出す。つまりSmartyクラスからオブジェクトを生成して、そのオブジェクトを持ちまわって、変数の割り当て処理等をおこなうのだ。
正規の手順で変数割り当て処理までおこなうのだから、当然この時点で終了しているであろうはずのPREフィルター処理は完了しているはずだ。

しかし描画処理はというと、Smartyの機能で完結しているわけではない。たいていのフレームワークでは、変数等の割り当てられたHTMLをfetchし、それをフレームワークの機能を使って出力していることが多い。つまりSmartyの正規の手順を踏まずにHTMLを出力していることになる。であれば、Smartyで最後におこなわれる処理(POSTフィルター)は実行されないまま、出力がおこなわれると考えることができるわけだ。

本来ならフレームワーク側で、Smartyの処理を最後まで面倒を見ないといけないはずなのだが、フレームワークによっては省略していることも多いようだ。

本件、ソースコードをじっくりみたわけではないのだが、おそらく上記のような理由で間違いないだろう。かなりはまってしまったのでメモ。

ちょっとしたデバッグ

2007/05/22 | Smarty

Smartyにはデバッグコンソール機能がついていて、あらかじめ設定しておくだけで、どのような変数にどのような値が格納されているかポップアップでだしてくれる。これはこれでとても便利。
しかしわざわざ設定を書き換えたりする必要があるので面倒だ。URLのQueryString中に、一時的に「SMARTY_DEBUG」の文字列を加えるとコンソールが出るとのことだが、意外とそれも面倒。
で、今日たまたま思いついた。テンプレート内の変数に修飾子を以下のようにつけてみた。

{$variable|var_dump}

テンプレート内で思うような処理ができなくって困っていたりするわけだから、テンプレートファイルを編集するだけで、ささっ、と変数の中身を調べたいとかねてから思っていた。ちょっと思いつきでやってみただけだったけど、ちゃんとvar_dumpしてくれた。

すっきり。
ほんの少しだけ手間が減った。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net