Home > webプログラム > Zend Framework

05月16日 

Zend Framework

Zend_Dbの連鎖操作は直下の階層のみ

Zend_Dbでは、テーブル間のリレーションを定義しておけば、親テーブルが削除された時に従属テーブルの対象も一緒に削除してくれる連鎖操作の削除機能があります。

親テーブル(Categories)に従属テーブル(Items)情報

PHP:
  1. protected $_dependentTables = array('Items');

従属テーブルに親テーブル情報

PHP:
  1. protected $_referenceMap = array(
  2.     'Categories' => array(
  3.         'columns' => 'category_id',
  4.         'refTableClass' => 'Categories',
  5.         'refColumns' => 'id',
  6.         'onDelete' => self::CASCADE
  7. );

と設定しておけば、

PHP:
  1. $categories = new Categories();
  2. $categories->find($id)->current()->delete();

とした時に、従属テーブルであるItemsのcategory_idが同一の物は削除される。

駄菓子菓子!

Itemsの従属テーブルとしてAttributesがあったとする。
(Categories→Items→Attributes)
となると、Categoriesを削除した時Itemsが削除されるのだから、当然Itemsの従属テーブルであるAttributesも削除されてしかるべき!と思う訳なんだけど、ところがどっこい、そうは行かない。
削除されるのは直下にあるItemsのみで、それ以降にあるAttributesは削除されない…
ちなみに、Itemsを削除するとAttributesは削除されるので、直下しか削除されないのは明白。。。

で、ググってみたところ一応出てきました解決策。
Zend_Db_Table_Abstractの_cascadeDelete()にある

PHP:
  1. $rowsAffected += $this->delete($where);

PHP:
  1. $toDelete = $this->fetchAll($where);
  2. foreach($toDelete as $row) {
  3.     $rowsAffected += $row->delete();
  4. }

でOKじゃね?との事。とりあえず検証してみたところ、意図したとおり2階層目以降も削除されてるようです。元のフレームワークに手を入れたくない場合は、_cascadeDelete()をオーバーライドすればOK。
参照先

あ、ちなみに_referenceMapの'refColumns'にはプライマリーキーを指定しないと駄目です。←ここでハマった…orz

なんだかバージョンアップごとに色々機能が増えてくれるのはいいんだけど…「Zend_Loaderは2.0で無くすぜ」とかZend_Applicationとか…ラーニングコストは高いよなぁ…
でもZendX_JQueryは興味津々なので、また勉強しなくっちゃ。