CakePHP1.3.6:HABTMの関係にあるデータを保存する
CakePHPのHABTM(hasAndBelongsTOMany)が面白いので興味本位に見てきたが、さて、データを登録するときにどうしたらいいのだろ、と思った。
これまで使ってきたItemとCategoryであれこれやってみた。
下のようなItem登録画面から、Categoryをマルチで選択して、登録する。このときに、ItemとCategoryの関係性(アソシエーション)も保存する。
結局、うまくいったのは、scaffoldでの登録画面のソースと、こちらの記事のおかげ。感謝です。
Itemをメンテナンスするscaffoldの画面ソースをみると、Category登録のselectタグのnameが
name=data["Category"]["Category"][]
となっていて、あれれと思った。
普通なら、data["Category"]["id"]とかになっていそう。
まず、ビュー(items/add.ctp)を以下のように書く。ここで、(a)をCategoryとだけ書くのがポイント。これで、name=data["Category"]["Category"]となる。(a)の部分を"Category.id"なんて書いてしまうと、name=data["Category"]["id"][]というHTMLが生成されて失敗する。
<h2>商品の登録</h2> <?php echo $form->create(null,array('type'=>'post','action'=>'add')); ?> <table> <?php echo "<tr><th>商品名</th>"; echo "<td>{$form->text('Item.name',array('size'=>'20'))}{$form->error('Item.name')} </td>"; echo "</tr>"; echo "<tr><th>カテゴリー</th>"; echo "<td>{$form->select("Category", // ...(a) $cus['data'], // array('id'=>'Customer.name') $cus['selected'], // selected array('multiple'=>true,'empty'=>false))}</td>"; echo "</tr>"; echo "<tr><th>メモ</th>"; echo "<td>{$form->textarea('Item.memo')}</td>"; echo "</tr>"; echo $form->end('登録'); ?> </table> <a href=".">リストに戻る</a>
これができれば、あとは簡単。items_controller.phpのaddアクションは以下のようにすればよい。
selectボックスを選択すれば、Item登録時にCategoryとのアソシエーションが登録され、選択しなければ、アソシエーションは(当たり前だけど)保存されない。
ここで、selectボックスの値をセットするために、初めてfind('list')を使ってみた。(b)のようにかけば、idをキーにするnameのリストが取得できる。
/** * * データの追加 * */ function add(){ $this->set('title_for_layout', "商品の登録"); if(!empty($this->data)){ // サニタイズ $this->data["Item"] = MyConverter::getRequestParams($this->data["Item"]); $this->data["Category"]["Category"] = MyConverter::getRequestParams($this->data["Category"]["Category"]); // 登録 if($this->Item->saveAll($this->data)){ // 登録できたらリダイレクト $this->redirect('.'); }else{ $this->Session->setFlash('データの保存に失敗しました'); } } // カテゴリーリストの作成; array('id'=>'name')の作成 $category = $this->Category->find('list',array('fields'=>array('id','name'))); // ... (b) // selectボックス用データの生成 $ret = array('data'=>$category,'selected'=>null); $this->set('cus',$ret); }