many-to-manyを殴り書き
今のところ、あまり必要に迫られているわけではないのですが、
覚書程度にDBICのmany-to-manyを試してみます。
Memberテーブル:Addressテーブル = n : m
みたいなな感じで。
package Proj::Schema::Member;
use strict;
use warnings;
use base 'Proj::Schema';__PACKAGE__->table('member');
__PACKAGE__->add_columns(qw/
id
rid
name
created_on
timestamp
/);
__PACKAGE__->set_primary_key(qw/id/);
__PACKAGE__->has_many('member_address' => 'Proj::Schema::MemberAddress','member');
__PACKAGE__->many_to_many('addresses' => 'member_address','address');1;
package Proj::Schema::Address;
use strict;
use warnings;
use base 'Proj::Schema';__PACKAGE__->table('address');
__PACKAGE__->add_columns(qw/
id
rid
city
created_on
timestamp
/);
__PACKAGE__->set_primary_key(qw/id/);
__PACKAGE__->has_many('member_address' => 'Proj::Schema::MemberAddress','address');
__PACKAGE__->many_to_many('members' => 'member_address','member');1;
MemberテーブルとAddressテーブルの間を取り持つテーブルを作成
package Proj::Schema::MemberAddress;
use strict;
use warnings;
use base 'Proj::Schema';__PACKAGE__->table('member_address');
__PACKAGE__->add_columns(qw/
member
address
created_on
timestamp
/);
__PACKAGE__->set_primary_key(qw/member address/);
__PACKAGE__->belongs_to('member'=>'Proj::Schema::Member');
__PACKAGE__->belongs_to('address'=>'Proj::Schema::Address');1;
こんな感じ。
Proj::Schema::Memberはhas_manyでProj::Schema::MemberAddressをもち
Proj::Schema::Addressもhas_manyでProj::Schema::MemberAddressを持ちます。
Proj::Schema::MemberAddressはそれぞれMemberとAddressに対してbelongs_toになると。
ここまでは特に変化球はないかと思うのですが、(たぶん)
Proj::Schema::MemberAddressではset_primary_keyで複数キーをプライマリ指定してます。
こっからめんどい。
many-to-many用の設定で、
Proj::Schema::Memberでは
__PACKAGE__->many_to_many('addresses' => 'member_address','address');
こんな設定をします。
addressesってのがmany-to-manyのキーみたいなのん。(アクセサになる)
member_addressってのがhas_manyしている設定のキー。
addressってのがMemberAddress(中間テーブル)からAddressテーブルにさかのぼる
キーで、設定したbelongs_toのキー。
Proj::Schema::Addressでは
__PACKAGE__->many_to_many('members' => 'member_address','member');
こんな設定。
membersがmany-to-manyのキー。
member_addressがhas_manyしている設定のキー。
memberってのがMemberAddress(中間テーブル)からMemberテーブルにさかのぼる
キーになる、設定したbelongs_toのキー。
こんな感じです。
実験スクリプト
## データの初期化(とりあえず全部消す)
$self->model('Member')->search({})->delete_all;
$self->model('Address')->search({})->delete_all;
$self->model('MemberAddress')->search({})->delete_all;## Memberテーブル作成
my $member1 = $self->model('Member')->create({name => 'タロウ'});
my $member2 = $self->model('Member')->create({name => 'ジロウ'});## Addressテーブル作成
my $address1 = $self->model('Address')->create({city => 'Tokyo'});
my $address2 = $self->model('Address')->create({city => 'Kyoto'});
my $address3 = $self->model('Address')->create({city => 'Osaka'});## MemberテーブルとAddressテーブルを関連付けするMemberAddressにデータ作成
## タロウ:Tokyo
## タロウ:Kyoto
## ジロウ:Tokyo
## ジロウ:Osaka
## こんな感じの設定
my $member_address1 = $self->model('MemberAddress')->create({member => $member1->id, address => $address1->id});
my $member_address2 = $self->model('MemberAddress')->create({member => $member1->id, address => $address2->id});
my $member_address3 = $self->model('MemberAddress')->create({member => $member2->id, address => $address1->id});
my $member_address4 = $self->model('MemberAddress')->create({member => $member2->id, address => $address3->id});## R実行
## Memberテーブルから全レコード取得
my $member_rs = $self->model('Member')->search({});
while (my $member = $member_rs->next) {
## XXX:many-to-many発動
## addressesはmany_to_manyで設定したキー(アクセサ)
my $address_rs = $member->addresses;
while (my $address = $address_rs->next) {
warn $member->name,':',$address->city;
}
}
こんな感じです。
説明適当ですが、分かるでしょう^^;
(うそは書いて無いとおもう。。)