LoginSignup
2
2

More than 5 years have passed since last update.

[Smarty] HTMLを出力する以外のSmarty活用法

Last updated at Posted at 2013-12-05

Smartyとは

PHPのテンプレートエンジンです。

テンプレートエンジンといえば、
MVCアーキテクチャのViewを担当していて
「HTMLを出力するもの」 みたいなイメージが強いですが
「条件に応じたテキストを吐き出す便利ツール」 として捉えたとき
「PHP内部で記述してるSQLも分離できるんじゃね?」 と思い立ちました。

そこで、自作フレームワークにおいてSQLを分離させてみました。
まずは下記のように、smartyのテンプレートディレクトリパスにSQLファイルを管理するディレクトリを追加。

ControllerBase.class.php
<?php
abstract class ControllerBase
{
    /* 一部抜粋 */
    protected $_smarty;

    private function _initializeTemplateEngine()
    {
        $this->_smarty = new Smarty();
        $this->_smarty->template_dir = array(
            SMARTY_TEMPLETE.DS.'sql',
            SMARTY_TEMPLETE.DS.'common',
            SMARTY_TEMPLETE.DS.$this->_controller.DS.$this->_action,
        );
        $this->_smarty->compile_dir = SMARTY_COMPILE.DS ;
        $this->_smarty->cache_dir   = SMARTY_CACHE.DS ;
        $this->_smarty->config_dir  = SMARTY_CONFIGS.DS ;
    }

    private function _setCollection()
    {
        $tables = Database::getTables(USE_DB);

        foreach ($tables as $v) {
            $this->_collection[$v] = CreateInstance::createModelInstance($v);

            /* (中略) */

            // テンプレートエンジンを利用する
            if (method_exists($this->_collection[$v], 'setTemplateEngine')) {
                $this->_collection[$v]->setTemplateEngine($this->_smarty);
            }
        }
    }

}

_initializeTemplateEngine() でSmartyのインスタンスを生成し、各種設定を行う。

_setCollection() で各モデルクラスのインスタンスを生成しつつ、_smarty のインスタンスをモデルでも共有する。

各モデルクラスは、ModelBase クラスを継承している(自作フレームワーク内の前提)ので
ModelBase クラスメソッドとして setTemplateEngine を定義する。

ModelBase.class.php
<?php
abstract class ModelBase extends ModelCore
{
    /* 一部抜粋 */

    protected $_smarty;
    protected $_sqlParams;

    public function __construct()
    {
        $this->_sqlParams = array();
        parent::__construct();
    }

    /* (中略) */

    public function setTemplateEngine($_obj)
    {
        $this->_smarty = $_obj;
    }

    protected function _makeQuery($_class, $_function)
    {
        $this->_smarty->assign('_sqlParams', $this->_sqlParams);
        return $this->_smarty->fetch($_class.DS.$_function.'.sql');
    }
}

各モデルクラスでは、データを取得するメソッド getData() を下記のように定義。

HogeFuga.class.php
<?php
class HogeFuga extends ModelBase
{
    public function getData($id)
    {
        // コメントからのご指摘 [#comment-d4c53ddaaa31e43d4ae8]
        // 入力されたパラメータには、適切なエスケープ処理を行うこと
        $this->_sqlParams['id'] = $id;
        $query = $this->_makeQuery(__CLASS__, __FUNCTION__);
        $row = $this->_result($query); // ModelCore 内で定義
        return $this->_formingResultRows($row); // ModelCore 内で定義
    }
}

最後に、SQLファイルを下記のように記述。

SMARTY_TEMPLETE.DS.'sql'.DS.'HogeFuga'.DS.'getData.sql'
SELECT * FROM {$_sqlParams._table} WHERE id={$_sqlParams.id}

この方法により、PHPスクリプト内部からSQL文が完全に分離でき
スクリプトの見通しがかなりスッキリしました。

細かい調整はここでは省略させていただきましたが
同一メソッド内で複数のクエリを発行したい場合などは、
smarty テンプレート内部で{if}{/if} などで分岐して記述することも可能です。
(個人的な目標は1メソッド1クエリー)

以上、ざざっと書いてしまいましたが、なにかのお役に立てば幸いです。

追記

SQLエスケープについて、下記をご参照ください。

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2