日記
Zend Frameworkをどう使うか その12Edit

もちろんこんなことになるなら、連番ではなくちゃんとしたセクションタイトルを付けるべきだったと後悔しているわけですよ。またZend_Dbネタの続きで、今度はselectクエリー生成ユーティリティクラスであるZend_Db_Selectクラスについて。

第一印象としては、Zend_Db_Selectに関しても、Zend_Db_Adapter::insertとかZend_Db_Adapter::updateとかと同様に、微妙に中途半端な感じがする。ちなみにZend_Db_Selectクラスの具体的な使い方としては、

// $db - Zend_Db_Adapterオブジェクト
$select = $db->select();
$select->from('tbl', '*'); // select * from tbl
$select->where('foo = ?', 1); // where foo = 1
$select->order('bar'); // order by bar
$select->limit(10, 5); // MySQLなら limit 10, 5
$sql = $select->__toString(); // select * from tbl where foo = 1 order by bar limit 10,5

って感じ。ちなみに上記サンプルには使ってないけど、他にもgroupとかhavingとかSQL文法要素のパターン一通り*1のメソッドがあって、メソッド名から想像したとおりに動く。

なんかもう「うわー」って感じがしない? こういうユーティリティクラスはそれなりに便利だとは分かる(昔自分でも作ったよ)けど、O/Rマッパー全盛の時代にこれをメインに使うのはちょっとビミョーな気がする。

ただ、こういうクラスが作られた理由は何となく想像できる。

というのは、後で触れるZend_Db_TableによるO/Rマッパー機能には、PEAR DB_DataObjectには存在したデータオブジェクト同士のjoin機能がなくなっている。DB_DataObjectでは、[dbname].links.iniにリンク情報を記述しておけば、

$foo = new FooTable(); // DB_DataObjectによるfooテーブルオブジェクト
$bar = new BarTable(); // DB_DataObjectによるbarテーブルオブジェクト
$foo->joinAdd($bar); // links.iniの設定に基づいて二つのテーブルをjoinする
$foo->find(); // select文を発行

なんて感じで、joinを使ったselect文をデータオブジェクト操作のレベルで書けたけど、Zend_Db_Table(_Row)からはそういう機能はすっぱり削除された。実際にはもちろんjoinを使ったselectなんて山のように使うわけで「O/Rマッパーのレベルでのjoin機能を削った代わりに、joinを伴う複雑なselectの管理はこっちでやってね」というんで作られたのが、Zend_Db_Selectなんじゃなかろうか。

まあ確かに、DB_DataObjectのjoin機能は結構微妙なできではあったし*2、その完成度を高めるってのはかなり難しい*3ことは分かるけど、こうなっちゃうと使い勝手としてはDB_DataObjectから後退している気がするんだよなー。単体ではきれいな仕様&実装ではあると思うけど。

ちなみにZend_Db_Selectを使ったjoinのやり方は、こんな感じになる。

$select = $db->select();
$select->from('foo', '*'); // select foo.* from foo
$select->join('bar', 'foo.id = bar.id', '*'); // select bar.* ... join bar on foo.id = bar.id
$sql = $select->__toString(); // select foo.*, bar.* from foo join bar on foo.id = bar.id

うーん、俺なら素直にSQL文+placeholderで書いちゃう気がするなー。Zend_Db_Selectを使っても、結局O/RマッパーであるZend_Db_Tableとは異なるオブジェクトに対する操作になってしまうし、だったらO/Rマッパーとは異なる形でSQL文を隠蔽するZend_Db_Selectを使うよりは、まだSQL文を直接書いた方がわかりやすい気がする。Zend_Db_Selectを使う場合は、生成されるSQL文を完全に頭の中にイメージしていないと使えないわけだし。

あ、一点Zend_Db_Selectを使う確実な利点があったな。limit関係のSQLはDBMSによっていろいろ異なるんだけど、それをZend_Db_Selectを使うことで吸収してくれる模様。それが重要ならば使う価値があるかもね。

*1 +追加条件の場合はorWhereとかorHavingとかの論理演算指定含む

*2 実用レベルでは、内部的に生成されるSQL文を意識しながら使う必要があったり

*3 DBスキーマ側まで規約で縛ったりすれば何とかなるかもしれないけど

Published At2006-03-24 00:00Updated At2006-03-24 00:00