Zend Frameworkで多対多のテーブルを簡単に扱う。

いろいろとややこしい多対多のテーブル関連の操作をZend Frameworkで簡単に行えます。
前提として、RDBMS上ですでにリレーションの設定を行っているものを扱います。そちらのほうが簡単なので。

多対多リレーションとか関係テーブルとか、マッピングテーブルとかいわれてるテーブルの設定。

[php]
class BugsProducts extends Zend_Db_Table_Abstract
{
protected $_name = ‘BugsProducts’;

protected $_referenceMap = array(
‘Bug’ => array(
‘columns’ => ‘bug_id’,
‘refTableClass’ => ‘Bugs’,
‘refColumns’ => ‘id’
),
‘Product’ => array(
‘columns’ => ‘product_id’,
‘refTableClass’ => ‘Products’,
‘refColumns’ => ‘id’
)
);

}
[/php]

(設定はZFマニュアルに載っているのを参考に、少し変更しました。あまり深く考える必要は無いのですが、まあ、BugsとProductsの多対多、1つの製品に多数のバグがあり、1つのバグが製品群に横行していることもある、といったテーブルでしょうか)
上記の様に親テーブルにリファレンスを張って、

[php]
$products = new Products();
$bug_list = $products->find(10)->current()
->findManyToManyRowset(‘Bugs’, ‘BugsReports’);
[/php]
で、$bug_listには、多対多テーブルで product_id=10 と関連付けられている (bugsテーブルの)bugのRowsetが入っているという。。
今時のフレームワーク、O/Rマッパーなどでは当たり前の機能なのかもしれませんが、こんなに簡単に操作できて感動しました。

RDBMS上でリレーションを組んでおけば、Zend_Db_Tableの設定で 親側のテーブルに $_dependentTables を指定しなくてもよいので楽です。

マニュアルには、

注意

RDBMS サーバが実装している参照整合性制約によって連鎖操作を行う場合は、 $_dependentTables を宣言しません。 詳細は 項9.8.6. 「書き込み操作の連鎖」 を参照ください。

と書いてあります。$_referenceMapも自動で張ってくれると楽なんですけどねえ。

findManyToManyの書き方は色々とあるようですので、マニュアルを参照してください。

[php]
$row->findVia()
$row->findViaBy()
$row->findViaByAnd()
[/php]