2014年5月10日土曜日

CakePHP で複数のデータベースのテーブルを Join する

先日、複数のサブシステムを統合した社内システムを開発してリリースした。
裏話というか Tips になるけど、
開発に着手しはじめ、技術仕様について考えていた時、もっとも考え込んだのはデータベース。
複数のサブシステムのあるシステムなので、サブシステム毎にデータベースを分けて管理したいと思っていた。

共通化出来るエンティティ群と4つのサブシステム毎にあるエンティティ群をリンクする必要がある事が分かり、
リンクが必要な際はデータベースが異なるテーブル同士を JOIN して。。。
しかし CakePHP で複数データベースを取り扱った事が無く、
また CakePHP のモデル同士を繋ぐアソシエーションの設定や Model->find のオプションで、異なるデータベースのテーブル同士の JOIN が可能なのかも知らなかった。
Model->query で出来るのは分かるけど、非常に便利なアソシエーションや Model->find で出来ないと CakePHP の恩恵が半減するので調べてみたところ、Model->find でも異なるデータベースの JOIN が出来るのが分かったのが大きかった。

実際に実装に組み込んだものだが、例として共通テーブルの Shop と、サブシステムAの Report テーブルを JOIN してみる。
※実際はもっとリファクタリングして共通化したりしているけれど

class Shop extends AppModel {

    public $useDbConfig = 'commons';

}

class Report extends AppModel {

    public $useDbConfig = 'sub-a-systems';

    public $belongsTo = array(
        'Shop' => array('type' => 'INNER'),
    );

}

class ReportsController extends AppController {

    public $uses = array('Report');

    public function index() {

        $model = $this->{$this->modelClass};

        $reports = $model->find('all', array(
            'fields' => array(
                'Report.*',
                'Shop.name AS shop_name',
            ),
            'joins' => array(
                array(
                    'type'       => 'INNER',
                    'tables'     => 'commons.shops',
                    'alias'      => 'Shop',
                    'conditions' => 'Report.shop_id = Shop.id'
                ),
            ),
            'recursive' => -1,
        );

    }

}
そう、ただ joins オプションの tables プロパティの値にテーブル名を入れれば出来るようでしたwww
もし同じような事を検討している人がいたならば、参考になれば幸いです。

[参考]
モデルの属性 — CakePHP Cookbook 2.x ドキュメント http://book.cakephp.org/2.0/ja/models/model-attributes.html

0 コメント :

コメントを投稿