ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

【感想】いまさらだけど「CakePHP2 実践入門」を読み返した

CakePHP3.1.8が最近リリースされましたね!

bakery.cakephp.org

と、世の中はCakePHP3の話題で盛り上がっているはずですが、私はまだ業務でCakePHP2を使っているわけですよ。

CakePHP2 実践入門 (WEB+DB PRESS plus)

CakePHP2 実践入門 (WEB+DB PRESS plus)

先月10日ぐらい打ち込んでいましたが、いまいちまだ覚えていないところが多かったので、昨日読み返してみました。

話変わるけど、個人的に面白いと思ったことは、ある程度知識をもって専門書を読むとすげー頭のなかに入ってくるのなんのって。初めての体験でした。

CakePHPを扱う上での基本的な内容を広く網羅

まぁMVC初めて触りましたーとか、そもそもPHPってなにー?っつー初心者向けではないかなと思います。

CakePHPチュートリアルが終わって、もう少し延長した内容がほしいなってので読むとうれしい本かなと。

個人的にうれしかったのは、最後のページのチートシートと、フレームワークの実行シーケンス表です。これはわかりやすい。

仕事でプログラム書いていると思うことは、チュートリアルは抑えておくのはもちろんですが、ほとんど書籍に書いてあること以上のことをやらないといけないわけです。それは本にも載っていなければネットにも載っていなので、中々楽はできません。

ただ、チートシートやシーケンス表があるとぱっと見れたり探せたり、また応用に使えたりなど結構便利な場面が多かったです。

また、Unitテストやパフォーマンス、デプロイの手法まで載っていたので、内容的には豊富なのかなと思いました。

ちなみに手を動かしながら読むのをおすすめします!!!「読むだけ」は知識ある人がやることだと読み返していて思いました。

CakePHP(2.x)勉強したいならこの本はオススメです!

網羅率は高いと思うので、CakePHPチュートリアル終わった人は興味ある人は是非読んでみるといいと思う。

ですが、いまはすでにバージョン3が出ているので、それを先に進めたほうがいいかなとは思います。時代はそこなので。。。

ただ、安定版はまだ2.xなので、仕事ではあと1年は生き残っているんじゃないかな。

CakePHP2 実践入門 (WEB+DB PRESS plus)

CakePHP2 実践入門 (WEB+DB PRESS plus)

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

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

<?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行ですむと思います。取得するときは頑張って書いたほうがのちのち楽じゃないかな。

【CakePHP2.x】指定したModelでPaginateしたいとき

ControllerでPaginate Componentを読んだら各ActionでPaginateのメンバー変数にぶっこめば良い

<?php
App::uses('AppController', 'Controller');
class MainsController extends AppController
{

    /**
     * Components
     *
     * @var array
     */
    public $components = array('Paginator');

    /**
     * index method
     *
     * @return void
     */
    public function index()
    {
        // ページネーションしたいモデルを指定する。
        // パラメータを詳細に書きたい場合は$this->find()のoptionと一緒
        $this->paginate = ['Item' => ['fields' => '*']];

        // ちなみに指定するだけならこれでもおk
        $items = $this->Paginate->paginate('Item');
        $this->set(compact('items'));
    }

...
}