cakephpでHABTMなアソシエーションが思うように動作しないので単純化テストする その1
実験環境
- cakephp1.2.1.8004
- webrootとかのディレクトリの配置をいじってあります
- smartyviewを使ってます http://blog.ecworks.jp/smartyview
- smartyサブディレクトリを省略していますAPP/views/smarty.php#61あたり
//$this->subDir = 'smarty';
function aa() { $args = func_get_args(); return call_user_func_array('aa', $args); }
要求仕様
- 商品「りんご」「みかん」「いちご」はカテゴリ「果物」に属している
- 商品「レタス」「きゅうり」「キャベツ」はカテゴリ「野菜」に属している
- 商品「トマト」はカテゴリ「果物」と「野菜」両方に属している
- 商品「仮登録」はaddオペレーション直後を想定し、どのカテゴリにも属してなく、隠し属性1(仮登録)をつける
- 商品「いちご」は隠し属性2(在庫切れ)をつける
- 商品「キャベツ」は隠し属性3(廃盤)をつける
- 商品は複数のカテゴリを持ち、カテゴリは複数の商品を持つ(HABTM)
- 商品は隠し属性というパラメータを持ち、数値の0〜3をが入る
データベース設計
- productsテーブルを作る
- id,name,hiddenフィールドを作る
- categoriesテーブルを作る
- id,nameフィールドを作る
- cakephpの規約に従ってcategories_productsテーブルを作る(2つのテーブル名を名前順に_でつなげる)
- product_id,category_idフィールドを作る(それぞれの単数形_id)
その結果のSQLダンプ
-- phpMyAdmin SQL Dump -- version 2.10.2 -- http://www.phpmyadmin.net -- -- ホスト: localhost -- 生成時間: 2009 年 6 月 12 日 12:32 -- サーバのバージョン: 5.0.41 -- PHP のバージョン: 5.2.5 SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; -- -- データベース: `exp` -- -- -------------------------------------------------------- -- -- テーブルの構造 `categories` -- CREATE TABLE `categories` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; -- -- テーブルのデータをダンプしています `categories` -- INSERT INTO `categories` VALUES (1, '果物'); INSERT INTO `categories` VALUES (2, '野菜'); -- -------------------------------------------------------- -- -- テーブルの構造 `categories_products` -- CREATE TABLE `categories_products` ( `product_id` int(11) NOT NULL, `category_id` int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- -- テーブルのデータをダンプしています `categories_products` -- INSERT INTO `categories_products` VALUES (3, 1); INSERT INTO `categories_products` VALUES (2, 1); INSERT INTO `categories_products` VALUES (5, 2); INSERT INTO `categories_products` VALUES (4, 2); INSERT INTO `categories_products` VALUES (1, 1); INSERT INTO `categories_products` VALUES (7, 1); INSERT INTO `categories_products` VALUES (6, 2); INSERT INTO `categories_products` VALUES (7, 2); -- -------------------------------------------------------- -- -- テーブルの構造 `products` -- CREATE TABLE `products` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `hidden` tinyint(4) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ; -- -- テーブルのデータをダンプしています `products` -- INSERT INTO `products` VALUES (1, 'りんご', 0); INSERT INTO `products` VALUES (2, 'みかん', 0); INSERT INTO `products` VALUES (3, 'いちご', 2); INSERT INTO `products` VALUES (4, 'レタス', 0); INSERT INTO `products` VALUES (5, 'きゅうり', 0); INSERT INTO `products` VALUES (6, 'キャベツ', 3); INSERT INTO `products` VALUES (7, 'トマト', 0); INSERT INTO `products` VALUES (8, '仮登録', 1);
モデル
APP/models/product.php
<?php class Product extends AppModel { var $name = 'Product'; var $hasAndBelongsToMany = array( 'Category' => array( 'className' => 'Category', 'joinTable' => 'categories_products', 'foreignKey' => 'product_id', 'associationForeignKey' => 'category_id')); } ?>
APP/models/category.php
<?php class Category extends AppModel { var $name = 'Category'; var $hasAndBelongsToMany = array( 'Product' => array( 'className' => 'Product', 'joinTable' => 'categories_products', 'foreignKey' => 'category_id', 'associationForeignKey' => 'product_id')); } ?>
scaffoldで動作確認
APP/controllers/products_controller.php
<?php class ProductsController extends AppController { var $name = 'Products'; //var $view = 'Smarty'; var $helpers = array('Html', 'Form'); var $uses = array('Product','Category'); var $scaffold; } ?>
APP/controllers/category_controller.php
<?php class CategoriesController extends AppController { var $name = 'Categories'; //var $view = 'Smarty'; var $helpers = array('Html', 'Form'); var $scaffold; } ?>
ここでアソシエーションに不備がないかをscaffoldを使ってチェック
- http://localhost/.../productsにアクセス
- 商品とカテゴリのテーブルを行き来して自由に編集できることを確認
- 以降APP/models/*はほとんどいじらない
全件表示するコントローラーとビュー
APP/controllers/products_controller.php
<?php class ProductsController extends AppController { var $name = 'Products'; var $view = 'Smarty'; var $helpers = array('Html', 'Form'); var $uses = array('Product','Category'); //var $scaffold; function index() { $products = $this->Product->find('all'); pr($products); $this->set('products', $products); } } ?>
APP/views/products/index.tpl
<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>
「トマト」だけ抜粋すると
... [6] => Array ( [Product] => Array ( [id] => 7 [name] => トマト [hidden] => 0 ) [Category] => Array ( [0] => Array ( [id] => 1 [name] => 果物 ) [1] => Array ( [id] => 2 [name] => 野菜 ) ) ) ...