cakephpでHABTMなアソシエーションが思うように動作しないので単純化テストする その2
カテゴリで絞り込み実験
- http://book.cakephp.org/ja/view/83/hasAndBelongsToMany-HABTM
- ここに書いてあるいくつかの記述方法を試してみる
- できるだけビューテンプレをいじらずに表示したい
カテゴリで絞り込み実験 〜 アソシエーション設定に検索条件を追記する方法
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非推奨
- 1.1では$this->Category->generateList(null, 'Category.id', null, '{n}.Category.id', '{n}.Category.name')