ちょいちょいHABTMを使うわりに(まあ、まだ2回しか使ったことないけど)毎回やり方を忘れるのでメモ。 っていうか、初めてHABTMを使ったときはいろいろつまづいたので、データ保存に関する記事もきっと俺は書いているだろうと思っていたら、実は書いてなかったというね……ま、そういうこともあるさ。
一例として、複数の人にメルマガを配信する、それも常に全員に同じメールを配信するのではなく、たまには特定の人にだけ配信したいような画面を作っていて、誰にどのメールを配信したのかをDBで管理したいと思ったときには、メルマガの内容を保存しているテーブルと、メルマガに登録しているユーザーのユーザー情報を保存しているテーブルをHABTMで結びつけるようなことがあるかもしれない。
そこで、ユーザーの情報を管理しているusersテーブルと、メルマガの内容を保存しているmagazinesテーブルをHABTMで関連づけ、それに対応するmagazines_usersテーブルを作成する。
テーブルができたら、メルマガ情報の方のモデルにこんなような内容を書く。
class Magazine extends AppModel {
var $name = 'Magazine';
//HABTMの関連づけ
$hasAndBelongsToMany = array('User' =>
array('className' => 'User',
'joinTable' => 'magazines_users',
'foreignKey' => 'magazine_id',
'associationForeignKey' => 'user_id',
'unique' => false,
),
);
}
そして、データの保存をコントローラーで行う。
class MagazinesController extends AppController {
~中略~
$this->Magazine->saveall($this->data, array('validate' => 'first'));
~中略~
}
基本的にはこれだけでデータの保存は可能なのだけれど、問題は渡されてくるデータの形にある。要するに$this->dataの中身がどのようになっているかが大事。
通常、テーブルにデータを入れる際には、$this->data[‘モデル名’][‘カラム名’]みたいな形でデータを渡すことになるけれど、HABTMのときはちょっと違う。今回の場合でいえば、テーブルがmagazines_usersでカラム名がuser_idだからってそれをそのままの形で$this->dataに渡すと、残念ながらデータは保存されない。
ではどうするか。
× $this->data['MagazinesUser']['user_id']
○ $this->data['User']['User']
こういう形でデータが渡ってこなければならない。
きちんと調べたわけではないから、もしかしたらこの解釈は間違っているのかもしれないけど、たぶん
$hasAndBelongsToMany = array('User' => array('className' => 'User')……
ここが両方ともUserになっていることが関係しているんじゃないかと……だから、この部分が変わればデータの形も変わってくるのではないかと思われる。
$hasAndBelongsToMany = array('Hiromi' => array('className' => 'Go')……
$this->data['Hiromi']['Go'];
みたいなね。
まあ、命名規約に則って書いたらきっとこんな形でデータを飛ばすようなことはないんじゃないかという気がしないでもないけど……。
ちなみにviewの中身は、こんな感じになるかしら。
//例えばチェックボックスでユーザーIDのデータを飛ばす場合
echo $form->checkbox('User.User', array('value' => $this->data['User']['id']))
まあ、HABTMの場合は一度の複数のデータを登録するだろうから、実際には’User.User.0’とか’User.User.1’とか、データを飛ばしたときに$this->data[‘User’][‘User’][]の形になるような書き方になると思うけど。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。