##初めに
個人的にアソシエーションに関して、非常に苦戦したと同時に、わかってきたのでアウトプット兼備忘録としてここに書く。
##アソシエーションとは
モデル同士の繋がりの事。
アソシエーションには4つの種類があります。
- hasOne
- hasMany
- belongsTo
- belongsToMany
この4種類を一個ずつ噛み砕いていきます。
##hasOneとは
関係性としては、1対1となる。
Cookbookの例をテーブル構造にして見てみる。
[https://book.cakephp.org/3.0/ja/orm/associations.html#hasone]
例:ユーザーは1つのプロフィールを持っている。
usersテーブル
id | first_name | last_name |
---|---|---|
1 | 太郎 | 山田 |
2 | 花子 | 佐藤 |
3 | 誠 | 田中 |
profileテーブル
id | user_id |
---|---|
1 | 1 |
2 | 2 |
3 | 3 |
profileテーブルには、usersテーブルのid
に対する外部キーuser_id
が存在する。
山田太郎
は、2
というプロフィールをもち、佐藤花子
は、3
というプロフィールをもっている。
ユーザー(山田太郎や佐藤花子)は、一つのプロフィール(2や3)をもっているが、プロフィールは、一人のユーザーをもっている訳ではない。
テーブルオブジェクトのinitialize()メソッドには、以下のように定義する。
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class UsersTable extends Table
{
public function initialize(array $config)
{
// モデル名を入れる
$this->hasOne('Profile');
}
}
##hasMany
関係性は、1対多。
Cookbookの例をテーブル構造にして見てみる。
[https://book.cakephp.org/3.0/ja/orm/associations.html#hasmany]
例:ユーザーは複数の記事を持つことができる。
usersテーブル
id | first_name | last_name |
---|---|---|
1 | 太郎 | 山田 |
2 | 花子 | 佐藤 |
3 | 誠 | 田中 |
articlesテーブル
id | user_id | title |
---|---|---|
1 | 1 | こんばんは |
2 | 1 | また明日 |
3 | 2 | 初めまして |
4 | 2 | よろしく |
5 | 3 | こんにちは |
山田太郎
は、こんばんは
とまた明日
という記事をもつ。
佐藤花子
は、初めまして
とよろしく
という記事をもつ。
usersテーブル
のid
に対し、user_id
を外部キーとして、articlesテーブル
に置く必要があります。
テーブルオブジェクトのinitialize()メソッドには、以下のように定義する。
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class UsersTable extends Table
{
public function initialize(array $config)
{
// モデル名を入れる
$this->hasMany('Articles');
}
}
##belongsTo
関係性は、多対1。
Cookbookの例をテーブル構造にして見てみる。
[https://book.cakephp.org/3.0/ja/orm/associations.html#belongsto]
例:多くの記事がユーザーに属している。
usersテーブル
id | first_name | last_name |
---|---|---|
1 | 太郎 | 山田 |
2 | 花子 | 佐藤 |
3 | 誠 | 田中 |
articlesテーブル
id | user_id | title |
---|---|---|
1 | 1 | こんばんは |
2 | 1 | また明日 |
3 | 2 | 初めまして |
4 | 2 | よろしく |
5 | 3 | こんにちは |
関係性としては、hasManyと逆のイメージ。
こんばんは
とまた明日
という記事は、山田太郎
というユーザーに属している。(山田太郎というユーザーの記事だ。という事)
同様に、初めまして
とよろしく
という記事は、佐藤花子
というユーザーに属している。
テーブルオブジェクトのinitialize()メソッドには、以下のように定義する。
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class ArticlesTable extends Table
{
public function initialize(array $config)
{
// モデル名を入れる
$this->belongsTo('Article');
}
}
##belongsToMany
関係性としては、多対多。
Cookbookの例をテーブル構造にして見てみる。
[https://book.cakephp.org/3.0/ja/orm/associations.html#belongstomany]
例:タグは多くの記事に属している。
articlesテーブル
id | user_id | title |
---|---|---|
1 | 2 | 初めまして |
2 | 3 | こんにちは |
3 | 1 | また明日 |
4 | 2 | よろしく |
5 | 1 | こんばんは |
article_tagsテーブル
id | article_id | tag_id |
---|---|---|
1 | 1 | 100 |
2 | 1 | 101 |
3 | 2 | 100 |
4 | 2 | 101 |
5 | 2 | 102 |
6 | 3 | 100 |
7 | 3 | 103 |
8 | 4 | 103 |
9 | 4 | 100 |
10 | 5 | 100 |
tagsテーブル
id | name |
---|---|
100 | 初心者 |
101 | 初投稿 |
102 | こんにちは |
103 | ありがとう |
この関係性をテーブル構造で表すと中間テーブルが必要になる。
記事の情報をもつarticlesテーブル
、タグの情報をもつtagsテーブル
、この二つのテーブルの架け橋的存在として、article_tagsテーブル
がある。
articleテーブル
のid
に対し、article_id
を外部キーとしてarticle_tagsテーブル
に置き、tagsテーブル
のid
に対し、article_id
を外部キーとしてarticle_tagsテーブル
に置く必要がある。
article_tagsテーブル
を見ると、初心者
というタグ(id = 100)は、初めまして
という記事に属していれば、こんにちは
という記事にも属している事がわかる。
article_tagsテーブル
(中間テーブル)から見ると、articlesテーブル
とtagsテーブル
はそれぞれ多対1の関係性になる。
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class ArticlesTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('モデル名');
}
}
##追記
今回記載しなかったが、アソシエーションを定義する時には、第二引数を連想配列の形または、関数呼び出し(->関数名()
)の形で条件を指定できる。
例として、第二引数を連想配列の形として定義した場合を記載する。
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
class ArticlesTable extends Table
{
public function initialize(array $config)
{
// 第二引数を連想配列として条件を定義
$this->アソシエーション名('モデル名', [
'foreignKey' => 'hoge_id',
'joinType' => 'INNER'
]);
}
}
foreignKeyや、joinType、が何を示しているのかわからない、または、他にどんな条件を定義できるかは、Cookbookを参考にして下さい。
参考:[https://book.cakephp.org/3.0/ja/orm/associations.html]
##まとめ
アソシエーションに関わらず、モデルの繋がり(関係性)の理解は非常に大切です。インターン先でそれを実感しています。基礎的な事を中心に書きましたが、応用的に使えるような事をもっと自分の中で落とし込める事ができたら、この記事に追記していこうと思います。
これらの内容に不備、間違った情報等記載してましたら、コメント貰えると嬉しいです。