院生エンジニアのにっき

  • Change style to Blue
  • Change style to Red
  • Change style to Green
  • Change style to Pink

CakePHP:ID以外のキーを用いて一時的に他テーブルとJOINする方法   2008-01-07

CakePHPアプリのモデルにおいて、UserBookモデルとBookモデルがあり、主キーは両方ともID。しかし両テーブルともASINというフィールドを持っていて、ASINフィールドを用いてJOINしたい場合のTips。

テーブルの意味的にはUserBook(user_books)テーブルがユーザが持っているテーブル、Book(books)テーブルが書籍情報を管理するテーブル。

テーブル構成としては

Book
UserBook
id(主キー)id(主キー)
asinasin
その他
その他

となっています。

UserBook側からBookに対してASINフィールドでJOINした結果を取得するためには、UserBookモデル側に

  1. function findAllWithBook($conditions, $fields, $order, $limit, $page, $recursive){
  2.   $bindInfo = array('hasOne' => array('Book' => array(
  3.     'className' => 'Book',
  4.     'foreignKey' => 'asin',
  5.   )));
  6.   $this->primaryKey = 'asin';
  7.   $this->bindModel($bindInfo);
  8.   $res = $this->findAll($conditions, $fields, $order, $limit, $page, $recursive);
  9.   $this->unbindModel($bindInfo);
  10.   $this->primaryKey = 'id';
  11.   return $res;
  12. }

でOK。

なにをしているかというと、findAll関数のラッパークラスfindAllWithBookで、primaryKeyを「asin」にしてからBookモデルと外部キー「asin」でbindModel、その後unbindModelをし、主キーをidに戻しています。

これで

SELECT
  `UserBook`.`id`, `UserBook`.`ASIN`, (UserBookの各フィールド),
  `Book`.`id`, `Book`.`ASIN`, (Bookの各フィールド)
  FROM `user_books` AS `UserBook`
  LEFT JOIN `books` AS `Book` ON (`Book`.`ASIN` = `UserBook`.`ASIN`)

としてasinフィールドでJOINした結果が取得できます。

※この場合、UserBookモデルにbelongsToなどのidを対象にJOINする関連付けがなされている場合おそらく「asin」フィールドに対してJOINするクエリを発行してしまうので注意して下さい。

こういった細かいことをする場合はやはり直接クエリを記述した方がいい様な気もします。。もしくは上記の例ですとUserBookテーブルにbook_idフィールドを作成するべきでしょうか。


コメントを書く