CakePHP5入門【コラム⑩】クロステーブル

A子
ToやCcに複数のメールアドレスを指定することで、同じ文面のメールを複数人へ一斉送信できるじゃん

B美
まぁ、その複数人がお互いに面識のない人物だったら、ちょっと問題が生じるけどね

C菜
そのメールを受け取った人は、知らない人のメールアドレスを労せずして入手できちゃうってことになりますし~
まぁ、Bcc(ブラインドカーボンコピー)だったら他人のメールアドレスは見えなくなりますけど~

A子
だから100人に同じメールを送りたければ、一人一人個別の送信処理(Toに一件だけ指定する)を100回繰り返す必要があるわけ
(もしも手作業だったら、めっちゃ面倒くさくてやってらんねぇ(笑))
でもさー
Webアプリケーション(CakePHP)では、メール送信って簡単にできるじゃない

C菜
データベーステーブルに複数人のメールアドレスを登録しておいて、そこから取得したレコードの数だけループを回せば良いんですね~
(100人分だったら100回のループを回して、ループの中で一件ずつ送信処理を行うって感じで…)

A子
名付けるなら「SPAMメーラー」って感じかな

B美
メールを送る相手からは必ず承諾を得ていないとね(つまりは、オプトイン)

A子

B美
同意ありが「オプトイン」ってこと
相手の同意なしに広告メールや詐欺メールを送りつけてくる業者が世の中にはたくさん存在するわけだけど、そういう奴らのことをSPAM業者なんて呼ぶわね
(なお、オプトアウトメールのことを一般的に「迷惑メール」とか「SPAMメール」って呼んだりします)

C菜

B美
(要するに、SPAMというのは商品名よ)
アメリカ製だから沖縄ではよく見かけるし、最近では(沖縄以外でも)ホームセンターなんかに置いてたりするわ

A子

B美
あるレストランを訪れた客が料理を注文しようとしたら、周りの客が一斉に「スパム!スパム!」って感じでSPAMコールするの
(SPAM入りの料理を注文しろ!…って意味)
要するにコメディ番組ね…ちなみにその客はSPAMが嫌いなの(笑)
あ、YouTubeにも動画があるから見てみると良いわ

C菜

B美
でも「悪名は無名に勝る」って言うし…

A子
んで、話は戻るけど、メールの一斉送信アプリって簡単に作れるよね?

B美
メールアドレスを格納するテーブルが一つだけなら簡単だと思うわよ
ただ、複数のグループを作ることができて、一つのグループに複数のメールアドレスを所属させることにする場合、ちょっと複雑になるかも…

C菜

A子
頭がこんがらがってきた(汗)
例えばだよ
「グループ」テーブルと「アドレス帳」テーブルがあって、こういう関係だとすると理解できるんだよ
【グループ】
id | グループ名 |
---|---|
1 | 従業員 |
【アドレス帳】
id | メールアドレス | ハンドルネーム | グループid |
---|---|---|---|
1 | ako@friction-river.jp | A子 | null |
2 | bimi@friction-river.jp | B美 | 1 |
3 | cina@friction-river.jp | C菜 | 1 |
これってB美とC菜の二人が「従業員」グループに所属しているってことね
(私は社長だから「従業員」グループじゃないわ)

C菜

A子
私とB美が「同窓会」グループに所属する場合、B美は二つのグループに所属することになるんじゃない?
さっきC菜が言ってたのって、こういうことだよね?
【グループ】
id | グループ名 |
---|---|
1 | 従業員 |
2 | 同窓会 |
【アドレス帳】
id | メールアドレス | ハンドルネーム | グループid |
---|---|---|---|
1 | ako@friction-river.jp | A子 | 2 |
2 | bimi@friction-river.jp | B美 | 1, 2 |
3 | cina@friction-river.jp | C菜 | 1 |
これって果たして可能なの?

B美
(だから「グループid」項目の中に複数の値を格納することはできないわ)
要するに、関係データベースでは「1対多(または多対1)」の関係をテーブル間に作ることはできるけど、「多対多」の関係は絶対に作れないの

C菜

B美
これはグループ側から見れば「1対多」ってこと
(「多」とは複数の意味ね…つまり、アドレスが複数ってこと)
一つのアドレスは複数のグループに所属させることができる
これってアドレス側から見れば、やっぱり「1対多」になるの
(グループが複数ってこと)
こういうとき「グループ」と「アドレス」は「多対多」であると言えるわけ
(なお、「1対多」や「多対多」という表現を「カーディナリティ」と総称します)

C菜

A子
そういうことかー
でも、それじゃ「多対多」は不可能だって結論で良いの?

B美
「多対多」を「1対多」と「多対1」に分解すれば良いのよ

A子

B美
【グループ】
id | グループ名 |
---|---|
1 | 従業員 |
2 | 同窓会 |
【交差】
id | グループid | アドレスid |
---|---|---|
1 | 1 | 2 |
2 | 1 | 3 |
3 | 2 | 1 |
4 | 2 | 2 |
【アドレス帳】
id | メールアドレス | ハンドルネーム |
---|---|---|
1 | ako@friction-river.jp | A子 |
2 | bimi@friction-river.jp | B美 |
3 | cina@friction-river.jp | C菜 |
ほら、「従業員」グループ(グループid:1)には私(アドレスid:2)とC菜(アドレスid:3)が、「同窓会」グループ(グループid:2)にはA子(アドレスid:1)と私(アドレスid:2)が所属しているってことが「交差」テーブルで示されてるでしょ?

C菜
(要するに、「交差」テーブルには外部キーが二つあります~)

A子
外部キー側は「多」になるんだから、「グループ」テーブルと「交差」テーブルは「1対多」
「交差」テーブルと「アドレス帳」テーブルは「多対1」ってことか…

B美
「グループ」テーブルと「アドレス帳」テーブルだけだと「多対多」になっちゃうけど、その間に「交差」テーブルを入れることで関係データベースでも実現可能になるのよ
(ちなみに「交差」テーブルのことを「クロス」テーブルと呼んだりもします)

A子
世の中には「多対多」になる事象も割と多いと思うんだけど、それらを関係データベースで表現できちゃう…ってことかぁ

C菜