[PHP] Smartyのテンプレートで動的にフラグを置き換える | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

例えば、Web-DBシステム構築時にこんな事ないでしょうか。


DB内のあるカラムには、そのアプリで必要なフラグ用の番号が格納されていて、そのフラグはプログラム内では様々な条件分岐で必要になるが、表示に関してはユーザーが分かる形(表示系データ)に置き換えて表示したい。


例)

DB上のデータ 実際に画面に表示したいデータ
1 作業A
2 作業B
3 作業C

このようなときに対応方法としては、



1. SQL(またはDB内)で最初から表示したいデータとして取ってしまう


CASE式を使ったSQLを書けば、直接フラグを整形したデータとして取得する事が可能です。

しかし、フラグ自体もシステム上のビジネスロジックでは必要な為、表示系データとフラグの2つを取らないといけない場合があったり、SQLに変換後の表示データが埋め込まれている為、データの定義が変わったりするとSQL自体も変更しなければならないなど、アプリの柔軟性に欠ける場合があります。


また、DBを正規化してしまってフラグと表示系データを格納するテーブルを分離させてしまっても良いですが、ちょっとしたフラグのために、別テーブルを作るのも少し面倒に思う場合があったりします。



2. プログラム内で変換テーブルを持ってしまう


これも良くある対応で、DBから取得したフラグを表示系データに変換する為のロジックを書いてしまうというものです。


例)

$data_list = array("1" => "作業A", "2" => "作業B", "3" => "作業C");
// $data_flgにはDBから取得したデータが格納されている
echo $data_list[$data_flg];

上記のように変換用の配列を用意しておき、フラグをキーにして表示系データを取得するというような感じです。

しかし、上記の変換は表示用のときのみ必要なデータになりますし、SQLの時と同じくその管理が面倒になります。



3. プログラム内で定数化しておく


2.より、もう少しスマートなやり方ですね。

今回の場合、Smartyのテンプレートを使う前提ですが、PHPで定義した定数をSmarty側から直接読み込むにはかなりロジカルなテンプレートを作ることになってしまうので、せっかくテンプレートとビジネスロジックを分離したのにそのうまみがなくなってしまいます。

Smartyのテンプレートを使用している場合、独自の関数を用意することで簡単にDBのフラグを表示系データに変換する事ができます。


例えば、こんな感じです。


- PHP側

<?php
require_once 'Smarty.class.php';

$smarty = new Smarty;
// 独自のSmarty関数(後述)が格納されているディレクトリ
$smarty->plugins_dir[] = 'my_plugins';

// work_catという変数をSmartyに受け渡し
// $db_work_flgにはDBから取得したフラグが格納されている
$smarty->assign('work_cat', $db_work_flg);
$smarty->display('template.tpl');

?>


- Template側

<table>
<tr>
<td>作業カテゴリ</td>
<td>{$work_cat|replace_flg}</td>
</tr>
</table>

これで、Smartyに渡した$work_flgが「1」であれば「作業A」が、「2」であれば「作業B」を表示するような事ができます。

では、Template内で呼び出している「replace_flg」というのは何かというと、今回独自に定義したSmarty用の関数です。
内容は、以下の感じ

- modifier.replace_flg.php

function smarty_modifier_replace_flg($string)
{
// $stringには関数への引数(今回の場合$work_flgの内容)が入ってくる
    switch ($string) {
        case 1: $string = "作業A"; break;
        case 2: $string = "作業B"; break;
        case 3: $string = "作業C"; break;
        default : break;
    }
    return $string;
}

Smartyの関数の中で、文字列を変換して返してあげているだけです。

Smarty内でオリジナルの関数を呼び出すようにするためには、決められた命名規則 で関数名とファイル名を定義し、Smartyから呼び出せるディレクトリ にそのファイルを配置します。


独自の関数を定義したファイル(modifier.replace_flg.php)を一番手っ取り早くセットする方法がSMARTY_DIR 内にある「plugins」ディレクトリに、作成した関数ファイルを置いてしまう方法なんですが、Smartyのコア関数も含まれる為、今回の場合は「my_plugins」ディレクトリに該当のプラグインファイルを配置しています。

これは、PHPプログラムの下記のところで読み込み先を指定しています。


$smartyplugins_dir[] = 'my_plugins';


システムで使用する定数を一覧化した設定ファイルが予めあるのであれば、それと組み合わせるともう少し保守が楽になるかもしれません。

また、Smartyの独自関数は複数の引数を渡す事もできますので、変換のパターンをバラエティに富んだものにすることもできます。


- modifier.replace_flg.php

function smarty_modifier_replace_flg($string, $flg)
{
// システムの定数が一覧化された設定ファイル
// define('HOGE', 'foo')とかが定義されている
    require_once 'config.php';

// $flgにはTemplate内で指定される第2引数で、変換パターンのフラグが入ってくる
    switch ($flg) {
// 作業フラグを表示系に変える
        case 'WORK':
// $stringには変換したいフラグデータが入ってくる
        switch ($string) {
// config.php内で定数化している
            case 1: $string = WORK_CATEGORY1; break;
           case 2: $string = WORK_CATEGORY2; break;
           case 3: $string = WORK_CATEGORY3; break;
           default : break;
        };
// ステータスフラグを表示系に変える
         case 'STATUS':
        switch ($string) {
            case 1: $string = "申請中"; break;
            case 2: $string = "完了"; break;
            default: break;
        };
        default: break;
    }
    return $string;
}


- Template側

<table>
<tr>
<td>作業カテゴリ</td>
<td>{$work_cat|replace_flg:'WORK'}</td>
</tr>
<td>ステータス</td>
<td>{$status_flg|replace_flg:'STATUS'}</td>
</tr>
</table>

replace_flgの後に「:」で第2引数を渡しています。

Smartyの関数は自由に定義できますので、Templateでしか使わないようなロジックはこのようにオリジナルの関数を作ってしまうとかなり便利です。