【CakePHP3】アソシエーションについて解説します




こんにちは、普段CakePHPで開発をしています。開発するにあたってControllerは良く使うのですが、Modelはよくわからない…となんとなく苦手意識があったので、アソシエーションについて勉強してみました。

今回はArticlesテーブルとUsersテーブルをアソシエーションで関連付けして一度にデータを引き出すところまでやってみます。

アソシエーションとは?

アソシエーションは直訳すると「関連」という意味があり、データベース絡みの文脈で言うアソシエーションはテーブル間の関連性を意味しています。具体的には、次の4種類が存在します。

hasOne(1:1)

いま、usersテーブルとprofilesテーブルが存在するとしましょう。プライマリーキーは、どちらもuser_idです。

【users】

user_idname
1Taro
2Hanako

【profiles】

user_idtelborn
1000-000-0000Tokyo
2999-999-9999Osaka

この2つのテーブルの関係を考えてみます。この場合は、どちらもuser_idという同じキーをプライマリーキーにしており、各レコードは1:1で対応しています。この1:1の関係を持つテーブルをhasOneといいます。

hasMany(多:1)

次に、usersテーブルとarticlesテーブルがあるとしましょう。プライマリーキーはそれぞれuser_idとidです。

【users】

user_idname
1Taro
2Hanako

【articles】

iduser_idtitlebody
11はじめての投稿おはようございます
212回目の投稿こんにちは
32はじめましてこんばんは

この場合、2つのテーブルの関係は1:1ではありません。何故ならば、1人のユーザーが複数の記事を書くことがあるからです。usersテーブルのuser_id一つに対して、articlesテーブルにはuser_idに対応するレコードが複数あります。実際、usersテーブルのuser_idが1のTaroには、articlesテーブルで2つのレコードが対応しています。これを「usersテーブルはarticlesテーブルに対してhasManyの関係を持つ」と言います。

belongsTo(1:多)

上で利用したusersテーブルとarticlesテーブルを引き続き使います。プライマリーキーはそれぞれuser_idとidです。

【users】

user_idname
1Taro
2Hanako

【articles】

iduser_idtitlebody
11はじめての投稿おはようございます
212回目の投稿こんにちは
32はじめましてこんばんは

この場合、articlesテーブルのレコードは、user_idをキーとして必ずuserテーブルのどれかのレコードに対応しています。つまりarticlesテーブルのすべてのレコードは、usersテーブルのいずれかのレコードに属している状態になります。このときarticlesテーブルはusersテーブルに対してbelongsToの関係を持つ、と言います。

belongsToMany(多:多)

そして最後に多:多の場合について説明します。例えば、記事は複数のタグを持ち、かつタグは複数の記事に割り振られます。

【articles】

idtitlebodytag
11番目の記事おはようございます1
22番目の記事こんにちは1
33番目の記事こんばんは2
44番目の記事おやすみなさい2

【tags】

idname
1science
2design

 

【中間テーブル】

idarticletag
11science
21design
32science
43science
54design

このように、記事は複数のタグを持っているし、タグは複数の記事に割り当てられる。この関係性をbelongsToManyと言います。

CakePHPのモデルで実装

CakePHPのモデルでアソシエーションを定義するメリットは、関連するテーブルのデータを一度に持ってきてくれることが一つあります。では実際に書いていきましょう。

データベースについて

データベースは以下の2つのテーブルがあるものとします。

【users】

user_idname
1Taro
2Hanako

【articles】

iduser_idtitlebody
11Taroの記事1Taroの記事1です。
22Hanakoの記事1Hanakoの記事1です。
31Taroの記事2Taroの記事2です。
42Hanakoの記事2Hanakoの記事2です。

Model

Modelは上の2つに対応したものを作成します。ちなみに、app名のフォルダのbinにあるcakeの実行ファイルを使って

と実行すると、Modelファイルを自動生成してくれる上に、アソシエーションも自動設定してくれます。では実際に作って見てみましょう。今回不要な部分は削除してあります。

UsersTable.php

ArticlesTable.php

usersテーブルの25行目と、articlesテーブルの19行目を見てください。それぞれhasManyとbelongsToが定義してあります。usersテーブルはarticlesテーブルに対して複数のレコード(記事)が対応するのでhasManyの関係、articlesテーブルのレコードはusersテーブルのどれかに属しているのでbelongsToの関係になっています。

Controller

こちらのControllerも自動生成して、今回不要な箇所を消しました。

ArticlesController.php

特に10行目のcontain(‘Users’)を見てください。このcontainは、アソシエーションを設定したUsersテーブルのデータも取ってくるというメソッドです。今回は配列で受け取りたいのでenableHydration(false)->toArray();をつけておきました。

これを$articlesという変数でviewに送ります。

index.ctp

そして、Controllerから送られてきた$articlesをdebug()で表示してみます。

その結果がこちらです。

デバッグ画面

この通り、’user’というキーの中に、記事を書いた著作者の情報が入っています!このようにアソシエーションをうまく活用することで、データのやりとりを効率的に行うことが出来るようになります。

まとめ

たくさんのテーブルを利用するようなウェブアプリケーションでは、テーブル間の関係を把握しておくことはとても大切です。確かにアソシエーションを一つ一つ考えていくのは大変ですが、後々効率的にデータを扱えるようになるので覚えておくのが良いと思いました。

belongsToManyなどは中間テーブルも絡んで頭がこんがらがりそうですが、これから勉強して慣れていこうと思います。