EthnaでテンプレートにDBを使用する方法
ちょっと、IRCで話題になったので作成してみました。
Ethnaのテンプレートに DB内に入っているリソースを使用する方法についてです。
DB内に格納されているデータを、テンプレートとして使用する方法として、Smartyのリソースプラグインを使用するのがお手軽でいいかと思います。
http://www.smarty.net/manual/ja/plugins.resources.php
サンプルとして、sampleというアプリケーションIDで作成してみます。
まずは、環境作成
ethna.shは、Ethna本体をインストールせずに使用するためです。
Smartyは、あらかじめ、パスの通してある箇所に展開済みとします。
$ mkdir sample $ cd sample $ svn export http://svn.sourceforge.jp/svnroot/ethna/ethna/tags/ETHNA_2_3_5/ lib/Ethna $ echo -e '#!/bin/sh\nexport ETHNA_HOME=$(dirname $0)/lib/Ethna\n$ETHNA_HOME/bin/ethna.sh "$@"' > ethna.sh
次に、プロジェクト作成
$ sh ethna.sh add-project -b ../ sample
後で、差分を確認するために、作成直後にコピーしておきます。
本来は必要ありません。
$ cp ../sample sample_base
テーブル構造
今回は、以下のような構造だとします。
create table tpl (name varchar(32),source blob,updatetime timestamp, primary key (name)); insert into tpl (name,source) values ('index','<html><body><h1>index</h1>index</body></html>');
実際には、期間切り替えやその他情報も入れる必要があるでしょう。
また、このDBに接続できるように、etc/sample-ini.phpに設定が追記する必要があります。
いじくる箇所
以下の箇所を変更します。
- Smartyプラグインを置くディレクトリを作成
- app/Sample_Controller.php に 作成したディレクトリへのパスを追加
- リソースプラグイン作成
- 該当Viewを変更(今回はIndex.php)
Smartyプラグインを置くディレクトリを作成
$ mkdir app/plugin/Smarty
app/Sample_Controller.php に 作成したディレクトリへのパスを追加
$directoryとういプロパティに、Smartyプラグインディレクトリへのパスを追加します。
$ vi app/Sample_Controller.php
<?php //色づけ /** * @var array アプリケーションディレクトリ */ var $directory = array( (略) 'locale' => 'locale', 'log' => 'log', 'plugins' => array('app/plugin/Smarty'), //追加 'template' => 'template', 'template_c' => 'tmp', (略) );
リソースプラグイン作成
$ vi app/plugin/Smarty/resource.db.php
<?php /* * Smarty plugin * ------------------------------------------------------------- * File: resource.db.php * Type: resource * Name: db * Purpose: Fetches templates from a database * ------------------------------------------------------------- */ function smarty_resource_db_source($tpl_name, &$tpl_source, &$smarty) { $ctl =& Ethna_Controller::getInstance(); $backend =& $ctl->getBackend(); $db =& $backend->getDB(); $sql = "SELECT source, updatetime FROM tpl WHERE name = ?"; $result = $db->db->getRow($sql, array($tpl_name), DB_FETCHMODE_ASSOC); if ($result && !DB::isError($result)) { $tpl_source = $result['source']; return true; } else { return false; } } function smarty_resource_db_timestamp($tpl_name, &$tpl_timestamp, &$smarty) { $ctl =& Ethna_Controller::getInstance(); $backend =& $ctl->getBackend(); $db =& $backend->getDB(); $sql = "SELECT source, updatetime FROM tpl WHERE name = ?"; $result = $db->db->getRow($sql, array($tpl_name), DB_FETCHMODE_ASSOC); if ($result && !DB::isError($result)) { $tpl_timestamp = $result['updatetime']; return true; } else { return false; } } function smarty_resource_db_secure($tpl_name, &$smarty) { // assume all templates are secure return true; } function smarty_resource_db_trusted($tpl_name, &$smarty) { // not used for templates } ?>
2回SQLをなげてしまっているので、実運用時にはもう一工夫必要です。
該当Viewを変更(今回はIndex.php)
$ vi app/view/Index.php
以下のメソッドを追加し、Ethna_Viewのメソッドをオーバーライドします。
<?php //色づけ /** * 遷移名に対応する画面を出力する * * 特殊な画面を表示する場合を除いて特にオーバーライドする必要は無い * (preforward()のみオーバーライドすれば良い) * * @access public */ function forward() { $renderer =& $this->_getRenderer(); $this->_setDefault($renderer); $this->forward_path = 'db:'. basename($this->forward_path, '.tpl'); $renderer->engine->display($this->forward_path); }
最後に
全ての変更でdiffをとってみたらこんな感じ。
$ diff -r -U2 -P sample_base sample diff -r -U2 -P sample_base/app/Sample_Controller.php sample/app/Sample_Controller.php --- sample_base/app/Sample_Controller.php 2008-06-25 14:00:27.000000000 +0900 +++ sample/app/Sample_Controller.php 2008-06-25 13:59:43.000000000 +0900 @@ -97,5 +97,5 @@ 'locale' => 'locale', 'log' => 'log', - 'plugins' => array(), + 'plugins' => array('app/plugin/Smarty'), 'template' => 'template', 'template_c' => 'tmp', diff -r -U2 -P sample_base/app/plugin/Smarty/resource.db.php sample/app/plugin/Smarty/resource.db.php --- sample_base/app/plugin/Smarty/resource.db.php 1970-01-01 09:00:00.000000000 +0900 +++ sample/app/plugin/Smarty/resource.db.php 2008-06-25 15:09:36.000000000 +0900 @@ -0,0 +1,51 @@ +<?php +/* + * Smarty plugin + * ------------------------------------------------------------- + * File: resource.db.php + * Type: resource + * Name: db + * Purpose: Fetches templates from a database + * ------------------------------------------------------------- + */ +function smarty_resource_db_source($tpl_name, &$tpl_source, &$smarty) +{ + $ctl =& Ethna_Controller::getInstance(); + $backend =& $ctl->getBackend(); + $db =& $backend->getDB(); + $sql = "SELECT source, updatetime FROM tpl WHERE name = ?"; + $result = $db->db->getRow($sql, array($tpl_name), DB_FETCHMODE_ASSOC); + if ($result && !DB::isError($result)) { + $tpl_source = $result['source']; + return true; + } else { + return false; + } +} + +function smarty_resource_db_timestamp($tpl_name, &$tpl_timestamp, &$smarty) +{ + $ctl =& Ethna_Controller::getInstance(); + $backend =& $ctl->getBackend(); + $db =& $backend->getDB(); + $sql = "SELECT source, updatetime FROM tpl WHERE name = ?"; + $result = $db->db->getRow($sql, array($tpl_name), DB_FETCHMODE_ASSOC); + if ($result && !DB::isError($result)) { + $tpl_timestamp = $result['updatetime']; + return true; + } else { + return false; + } +} + +function smarty_resource_db_secure($tpl_name, &$smarty) +{ + // assume all templates are secure + return true; +} + +function smarty_resource_db_trusted($tpl_name, &$smarty) +{ + // not used for templates +} +?> diff -r -U2 -P sample_base/app/view/Index.php sample/app/view/Index.php --- sample_base/app/view/Index.php 2008-06-25 14:00:27.000000000 +0900 +++ sample/app/view/Index.php 2008-06-25 15:02:11.000000000 +0900 @@ -25,4 +25,20 @@ { } + + /** + * 遷移名に対応する画面を出力する + * + * 特殊な画面を表示する場合を除いて特にオーバーライドする必要は無い + * (preforward()のみオーバーライドすれば良い) + * + * @access public + */ + function forward() + { + $renderer =& $this->_getRenderer(); + $this->_setDefault($renderer); + $this->forward_path = 'db:'. basename($this->forward_path, '.tpl'); + $renderer->engine->display($this->forward_path); + } } ?> diff -r -U2 -P sample_base/etc/sample-ini.php sample/etc/sample-ini.php --- sample_base/etc/sample-ini.php 2008-06-25 14:00:27.000000000 +0900 +++ sample/etc/sample-ini.php 2008-06-25 22:18:35.000000000 +0900 @@ -15,5 +15,5 @@ // db // sample-1: single db - // 'dsn' => 'mysql://user:password@server/database', + 'dsn' => 'mysql://user:password@server/database', // // sample-2: single db w/ multiple users