読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

【CakePHP2.x】アソシエーションで3つ以上繋げるならjoinに変更したほうが良い

CakePHP2.x CakePHP PHP

スポンサードリンク

というのもですね。こういうアソシエーションを用意しました。

<?php
...
    public function bindItemAndOrder($bool = true)
    {
        $orderModel = ClassRegistry::init('ItemsOrdersRelation');
        $orderModel->bindModel([
            'belongsTo' => [
                'Order' => [
                    'className' => 'Order',
                    'foreignKey' => 'orders_id'
                ],
                'Item' => [
                    'className' => 'Item',
                    'foreignKey' => 'items_id'
                ]
            ]
        ], $bool);
        $orderModel->Order->bindModel([
            'belongsTo' => [
                'Customer' => [
                    'className' => 'Customer',
                    'foreignKey' => 'customers_id'
                ]
            ]
        ], $bool);
        $orderModel->Item->bindModel([
            'belongsTo' => [
                'ItemSize' => [
                    'className' => 'itemSize',
                    'foreignKey' => 'item_sizes_id'
                ]
            ]
        ], $bool);
    }

個人的にアソシエーションはデフォでは設定しません。解除するのが大変&sql queryがいっぱい発行されて重くなるので。

なので↑のコードのように、bindModel()を実行するメソッドを用意してアソシエーションするわけです。

今回は注文テーブル(Order)、商品テーブル(Item)、注文と商品を繋げる交差テーブル(ItemsOrdersRelation)。

誰が注文したの?の顧客情報テーブル(Customer)、商品の大きさを保存している商品サイズテーブル(ItemSize)を用意しました。

Order -> ItemsOrdersRelation -> Item
Order -> Customer
Item -> ItemSize

って関係を持っています。

んで、このメソッドを実行したあとにfind('all')を実行してみるわけですよ。するとですよ。作成されたqueryがなんと30行!!!

え、私のquery多すぎ。。。

とまぁ、このようにアソシエーションはデータ保存するときの処理が楽で個人的にはすごく重宝していますが、それ以外とくにデータの引っ張り出しがすごくだるいです。

ということで、そういうデータは自分でjoinを書いて実行しましょう。

<?php
...
    public function getJoins() {
        return [
                'fields' => '*',
                'joins' => [
                    [
                        'type' => 'inner',
                        'table' => 'orders',
                        'alias' => 'Order',
                        'conditions' => 'ItemsOrdersRelation.orders_id = Order.id'
                    ],
                    [
                        'type' => 'inner',
                        'table' => 'items',
                        'alias' => 'Item',
                        'conditions' => 'ItemsOrdersRelation.items_id = Item.id'
                    ],
                    [
                        'type' => 'inner',
                        'table' => 'customers',
                        'alias' => 'Customer',
                        'conditions' => 'Order.customers_id = Customer.id'
                    ],
                    [
                        'type' => 'inner',
                        'table' => 'item_sizes',
                        'alias' => 'ItemSize',
                        'conditions' => 'Item.item_sizes_id = ItemSize.id'
                    ]
                ]
        ];
    }

    public function getData() {
        $itemsOrdersRelation = ClassRegistry::init('ItemsOrdersRelation');
        $joinParam = $this->getJoins();
        return $itemsOrdersRelation->find('all', $joinParam);
    }

これだとqueryが1行ですむと思います。取得するときは頑張って書いたほうがのちのち楽じゃないかな。