Smartyとは
PHPのテンプレートエンジンです。
テンプレートエンジンといえば、
MVCアーキテクチャのViewを担当していて
「HTMLを出力するもの」 みたいなイメージが強いですが
「条件に応じたテキストを吐き出す便利ツール」 として捉えたとき
「PHP内部で記述してるSQLも分離できるんじゃね?」 と思い立ちました。
そこで、自作フレームワークにおいてSQLを分離させてみました。
まずは下記のように、smartyのテンプレートディレクトリパスにSQLファイルを管理するディレクトリを追加。
<?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 を定義する。
<?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()
を下記のように定義。
<?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ファイルを下記のように記述。
SELECT * FROM {$_sqlParams._table} WHERE id={$_sqlParams.id}
この方法により、PHPスクリプト内部からSQL文が完全に分離でき
スクリプトの見通しがかなりスッキリしました。
細かい調整はここでは省略させていただきましたが
同一メソッド内で複数のクエリを発行したい場合などは、
smarty テンプレート内部で{if}{/if}
などで分岐して記述することも可能です。
(個人的な目標は1メソッド1クエリー)
以上、ざざっと書いてしまいましたが、なにかのお役に立てば幸いです。
追記
SQLエスケープについて、下記をご参照ください。