Zend Framework 日めくりカレンダー2011の7日目、「間に合ってない」ってツッコミには土下座しつつ、Zend_Db_Tableをもっと手軽に使う(概要編) #ZFhimekuriの続き。
Githubに上げたサンプルコードの解説を書きます。
趣旨は「とにかくユルく、ActiveRecord風にZend_Db_Table
を使う」です。
1) 初期化はapplication.iniに。
データベースの接続先やパスワードをどこに書くかは開発者の悩みの種です。
素直にZend_Application
をベースにしているアプリの場合は、application.iniに設定を書くだけでZend_Db
を初期化できます。
実際に使用するまでDBに接続しないので、実際にDBを使わないページが多くても安心です。
[production]
; ...
resources.db.adapter = "Pdo_Sqlite"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/performance.db"
; ...
パスワードを直接埋め込むのはセキュリティの意識としてあまりよろしくないので、必要なら設定ファイルを分割するといいです。
参考:DBのパスワードをapplication.iniから取り除く
Zend_Db_Table
を使うのであれば特に気にせずnewすればいいですが、直接Zend_Db
を使いたいときはBootstrap経由で取得する必要があります。
<?php
class HogeController extends Zend_Controller_Action
{
public function hogeAction() {
$db = $this->getInvokeArg('bootstrap')->db;
//アダプターを使ってPDOのようにSQLを直接書いたり色々
// ...
}
//...
}
2) DBのテーブル定義もConfigfileに。Zend_Db_Table_Definitionを利用する
公式のQuickStartではテーブル定義をZend_Db_Table
をextendsしたクラス(Model_DbTable_XXXX)に直接書いていました。でも、どうせ大した記述量じゃないのにテーブル一つ一つに対してクラスを作るなんて面倒ですよね。。
Zend_Db_Table_Definition
を使うと、テーブル定義をひとまとめに出来ます。
http://framework.zend.com/manual/ja/zend.db.table.definition.html
設定ファイルは、Zend_Config
を使ったほうがいいのですが、面倒なので素のPHPにしてしまいましょう。配列をreturnしているだけのPHPファイルでスキーマ定義を書きます。
<?php
return array(
/**
* postsテーブルスキーマ定義
*
*/
'posts' => array(
'name' => 'posts', //DB上の実際のテーブル名
'primary' => 'id',
'rowClass' => 'Model_Post',
),
//テーブルが他にあれば同じように追加していく
);
これで、スキーマの定義を一箇所にまとめることが出来ました。あとは、テーブル定義を取得するには以下のコードを実行します。
<?php
$config = include APPLICATION_PATH . '/configs/schema.php';
$schema = new Zend_Db_Table_Definition($config);
$postsTable = new Zend_Db_Table('posts', $schema);
//$postsTableを使って処理を色々
3) テーブル取得はグローバル関数にしてしまえ
たくさん作る必要があったクラスをまとめて消去できましたが、テーブル取得のコードが長いですね。
「ゆるく作る」が今回のコンセプトなので、グローバル関数にしてしまいましょう。
library/functions.phpにAR()という関数を定義しておき、public/index.phpでincludeしておきます。
<?php
function AR($name) {
static $schema, $cache = array();
if (isset($cache[$name])) {
return $cache[$name];
}
if (!isset($schema)) {
$config = require APPLICATION_PATH . '/configs/schema.php';
$schema = new Zend_Db_Table_Definition($config);
}
return $cache[$name] = new Zend_Db_Table($name, $schema);
}
<?php
// ...(中略) ...
require_once 'functions.php';
// ...(後略) ...
これで、テーブルの取得はAR('posts')のような短いコードで出来るようになります。
4) Tableを拡張するのではなくRowを拡張する
用語解説で「Zend_Db_TableはActiveRecordでない」と書きましたが、Zend_Db_Table_Row
を拡張すればかなりActiveRecordに近づけることが可能です。QuickStartの書き方が理想的なのですが、もっとカジュアルに書きたい場合はActiveRecord風にした方が楽だと思います。
Zend_Db_Table_Row
をextendsしてActiveRecord的ないわゆる「モデル」を作ります。今回の例だとModel_Post
クラスになります。
モデルはZendFramework標準状態なら「Model_」から名前を始めるようにし、modelsディレクトリに配置しておけば、自動で読み込まれます。
作ったクラスはZend_Db_Table_Definition
に「rowClass」として設定しておくと、通常はZend_Db_Table_Row
が使われるところを自作のクラスに差し替えたことになります。
<?php
class Model_Post extends Zend_Db_Table_Row_Abstract
{
//modifiedを自動更新するよう、save()をオーバーライド
function save() {
$this->modified = date('c');
return parent::save();
}
//モデル固有のメソッドを追加
function sayHello() {
echo 'Hello ' . __CLASS__;
}
}
あとはPostモデルにバリデーションロジックを増やしたり、get/setの際に自動変換を割りこませたり、色々機能を増やしてぶくぶく太らせていけばいいわけです。
具体的な利用イメージはZend_Db_Tableをもっと手軽に使う(概要編) #ZFhimekuriを参照してください。
かっちり作るもよし、この程度のユルさで作るもよし。Zend_Db_Table
はそれだけ拡張性が考えられたコンポーネントなのです。