cakephpでHABTMなアソシエーションが思うように動作しないので単純化テストする その2

カテゴリで絞り込み実験

カテゴリで絞り込み実験 〜 アソシエーション設定に検索条件を追記する方法

APP/controllers/products_controller.php
<?php
...
    function index() {
        $this->Product->bindModel(array(
            'hasAndBelongsToMany' => array(
                'Category' => array(
                    'conditions'=>array(
                        'Category.id'=>1)))));
        $products = $this->Product->find('all');
        
        pr($products);
        $this->set('products', $products);
    }
...
?>
結果
  • 全レコードが表示された
  • Category.id=1のレコードは[Category]以下に詳しい情報が取れてる
  • Category.id=1でないレコードは[Category]が空配列
    • こんなレコードはイラネッ(゜Д゜=)ノ⌒゜
  • 結論=>この書き方では不要なレコードまで取ってきてしまうので使えない
  • なお$products(抜粋)はこうなってた
...
    [6] => Array
        (
            [Product] => Array
                (
                    [id] => 7
                    [name] => トマト
                    [hidden] => 0
                )

            [Category] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => 果物
                        )

                )

        )
    [7] => Array
        (
            [Product] => Array
                (
                    [id] => 8
                    [name] => 仮登録
                    [hidden] => 1
                )

            [Category] => Array
                (
                )

        )

カテゴリで絞り込み実験 〜 モデルを重ねて絞り込む方法

APP/controllers/products_controller.php
<?php
...
    function index() {
        $products = $this->Product->Category->find(
            'all',
            array(
                'conditions' => array(
                    'Category.id' => 1)));
        pr($products);
        $this->set('products', $products);
    }
...
?>
結果
  • 1件も表示されない
  • Category.id=1のレコードが[Product]以下に配列で入ってる
  • 単純find()と配列の入れ方が違う
    • テンプレ側の書き方を変えれば表示できそう
  • テンプレ側の書き方を変えたくないので不適当
  • なお$productsはこうなってた
Array
(
    [0] => Array
        (
            [Category] => Array
                (
                    [id] => 1
                    [name] => 果物
                )

            [Product] => Array
                (
                    [0] => Array
                        (
                            [id] => 3
                            [name] => いちご
                            [hidden] => 2
                        )

                    [1] => Array
                        (
                            [id] => 2
                            [name] => みかん
                            [hidden] => 0
                        )

                    [2] => Array
                        (
                            [id] => 1
                            [name] => りんご
                            [hidden] => 0
                        )

                    [3] => Array
                        (
                            [id] => 7
                            [name] => トマト
                            [hidden] => 0
                        )

                )

        )

)

カテゴリで絞り込み実験 〜 結合テーブルのモデルをhasOne設定する方法

APP/controllers/products_controller.php
<?php
...
    function index() {
        $this->Product->bindModel(array('hasOne' => array('CategoriesProduct')));
        $products = $this->Product->find(
            'all',
             array(
                'conditions'=>array(
                    'CategoriesProduct.category_id' => 1)));
        pr($products);
        $this->set('products', $products);
    }
...
?>
結果
  • 期待通りにCategoriesProduct.category_id=1(つまりcategory.id=1)のレコードを取得できてる
  • 単純find()と配列の入り方が同じで、テンプレ側の書き方を変えずに表示できた
  • 結論:この方法が最適!オススメ
  • なお$productsはこうなってた
Array
(
    [0] => Array
        (
            [Product] => Array
                (
                    [id] => 3
                    [name] => いちご
                    [hidden] => 2
                )

            [CategoriesProduct] => Array
                (
                    [product_id] => 3
                    [category_id] => 1
                )

            [Category] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => 果物
                        )

                )

        )

    [1] => Array
        (
            [Product] => Array
                (
                    [id] => 2
                    [name] => みかん
                    [hidden] => 0
                )

            [CategoriesProduct] => Array
                (
                    [product_id] => 2
                    [category_id] => 1
                )

            [Category] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => 果物
                        )

                )

        )

    [2] => Array
        (
            [Product] => Array
                (
                    [id] => 1
                    [name] => りんご
                    [hidden] => 0
                )

            [CategoriesProduct] => Array
                (
                    [product_id] => 1
                    [category_id] => 1
                )

            [Category] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => 果物
                        )

                )

        )

    [3] => Array
        (
            [Product] => Array
                (
                    [id] => 7
                    [name] => トマト
                    [hidden] => 0
                )

            [CategoriesProduct] => Array
                (
                    [product_id] => 7
                    [category_id] => 1
                )

            [Category] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => 果物
                        )

                    [1] => Array
                        (
                            [id] => 2
                            [name] => 野菜
                        )

                )

        )

)

カテゴリで絞り込み実験 〜 結合テーブルのモデルをhasOne設定し名前で検索する方法

APP/controllers/products_controller.php
<?php
...
    function index() {
        $this->Product->bindModel(array(
            'hasOne' => array(
                'CategoriesProduct',
                'FilterCategory' =>array(
                    'className' => 'Category',
                    'foreignKey' => false,
                    'conditions' => array('FilterCategory.id = CategoriesProduct.category_id')))));
        $products = $this->Product->find(
            'all',
             array(
                'conditions'=>array(
                    'FilterCategory.name'=>'果物')));
        pr($products);
        $this->set('products', $products);
    }
...
?>
結果
  • 期待通りにcategory.name='果物'のレコードを取得できてる
  • 単純find()と配列の入り方が同じで、テンプレ側の書き方を変えずに表示できる
  • 結論→今回はカテゴリリストを生成しセレクタを表示する予定なのでcategory.name='果物'のように文字列でフィルタする必要がない
  • なお$products(抜粋)はこうなってた
...
    [3] => Array
        (
            [Product] => Array
                (
                    [id] => 7
                    [name] => トマト
                    [hidden] => 0
                )

            [CategoriesProduct] => Array
                (
                    [product_id] => 7
                    [category_id] => 1
                )

            [FilterCategory] => Array
                (
                    [id] => 1
                    [name] => 果物
                )

            [Category] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [name] => 果物
                        )

                    [1] => Array
                        (
                            [id] => 2
                            [name] => 野菜
                        )

                )

        )

)

結合テーブルのモデルをhasOne設定する方法を採用してカテゴリフィルタのオペレーションを作りこむ

APP/controllers/products_controller.php
<?php
...
    function index() {
        if($this->params['data']['Category']['id'] != ''){
            $this->Product->bindModel(array('hasOne' => array('CategoriesProduct')));
            $products = $this->Product->find(
                'all',
                 array(
                    'conditions'=>array(
                        'CategoriesProduct.category_id' => $this->params['data']['Category']['id'])));
        }else{
            $products = $this->Product->find('all');
        }
        $this->set('products', $products);
        $this->set('category_list',$this->Category->find('list'));
    }
...
?>
APP/views/products/index.tpl
{$form->create("Product", $view->aa('action','index'))}
{$form->select('Category.id',$category_list)}
{$form->end('検索')}
<br />

<table cellpadding="0" cellspacing="0">
<tr>
  <th>名前</th>
  <th>表示</th>
  <th>操作</th>
</tr>
{foreach from=$products item='product'}
  <tr>
    <td>
    {assign var='id' value= $product.Product.id}
    {$html->link($product.Product.name, "view/$id")}
    </td>
    <td>
    {$product.Product.hidden}
    </td>
    <td>
      {$html->link('編集', "/products/edit/$id")} 
      {$html->link('削除', "/products/delete/$id")}
    </td>
</tr>
{/foreach}
</table>
カテゴリをセレクタで表示するには
  • $this->set('category_list',$this->Category->find('list'));でカテゴリテーブルのid=>nameを配列に入れてビューに渡す
  • {$form->select('Category.id',$category_list)}でビュー展開
  • $this->params['data']['Category']['id']に値が入ってるならhasOne設定して検索
  • $this->params['data']['Category']['id']に値がないなら全件取得
  • $this->Category->find('list')
    • 中身はこんな感じ
Array
(
    [1] => 果物
    [2] => 野菜
)
    • 1.1では$this->Category->generateList(null, 'Category.id', null, '{n}.Category.id', '{n}.Category.name')
      • 1.2非推奨