初めに
個人的にアソシエーションに関して、非常に苦戦したと同時に、わかってきたのでアウトプット兼備忘録としてここに書く。
アソシエーションとは
モデル同士の繋がりの事。
アソシエーションには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]
まとめ
アソシエーションに関わらず、モデルの繋がり(関係性)の理解は非常に大切です。インターン先でそれを実感しています。基礎的な事を中心に書きましたが、応用的に使えるような事をもっと自分の中で落とし込める事ができたら、この記事に追記していこうと思います。
これらの内容に不備、間違った情報等記載してましたら、コメント貰えると嬉しいです。