さて表題通り、CakePHPにはモデル間のアソシエーションを定義することでリレーショナルデータベースを構築できます。
CakePHP には4つのアソシエーションが用意されています。hasOne, hasMany, belongsTo, そして hasAndBelongsToMany (HABTM) です。
Cookbookには以下のように説明がされています。
hasOne(1 対 1)
hasMany(1 対 多)
belongsTo(多 対 1)
hasAndBelongsToMany(多 対 多)
言い換えると以下のような感じになる。
hasOne:相手テーブルに、自分テーブル.idの外部キーをもっている(この外部キーはユニークである)
hasMany:相手テーブルに、自分テーブル.idの外部キーをもっている(この外部キーは複数ある)
belongsTo:自テーブルに、相手テーブル.idの外部キーをもっている
hasAndBelongsToMany:中間テーブル テーブル1とテーブル2の情報をもっている
※「hasOne」と「hasMany」の関連性はほぼ同じですが、ユーニークかじゃないかの違いみたいです。
少し具体的な部分をCakePHPのCookbookを見ながら理解を深めていきます。
【hasOne】
class User extends AppModel {
public $hasOne = array(
'Profile' => array(
'className' => 'Profile',
'conditions' => array('Profile.published' => '1'),
'dependent' => true
)
);
}
UserテーブルとProfileテーブルがあります。
Profileテーブルは、1つのUser.id(ユーザーid)を持っていることになります。
hasOneですので、 プロフィール情報は1つユーザーに1つしかない。当たり前ですが、このような関係をhasOneで定義します。
———
【hasMany】
class User extends AppModel {
public $hasMany = array(
'Comment' => array(
'className' => 'Comment',
'foreignKey' => 'user_id',
'conditions' => array('Comment.status' => '1'),
'order' => 'Comment.created DESC',
'limit' => '5',
'dependent' => true
)
);
}
UserテーブルとCommentテーブルがあります。
Commentテーブルは、ユーザーid情報を持っています。Commentテーブルには同じユーザーidを持っているレコードが複数存在します。
1ユーザーが複数のコメントを投稿出来るため、ユーザーとコメントの関連性はhasManyで定義することになります。
———
【belongsTo】
class Profile extends AppModel {
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
}
さてbelongsToの定義です。
先ほどhasOneの定義で、UserモデルからProfileモデルにアクセスできるようになりました。
視点を逆にしてみます。プロフィールテーブルにはユーザーid(外部キー)を含んでいるため、Userテーブルに属しているということになります。
その場合にProfileテーブルは、UserテーブルとbelongsToの関係で定義することになります。
———
【hasAndBelongsToMany (HABTM)】
class Recipe extends AppModel {
public $hasAndBelongsToMany = array(
'Ingredient' =>
array(
'className' => 'Ingredient',
'joinTable' => 'ingredients_recipes',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'ingredient_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => ''
)
);
}
最後にhasAndBelongsToManyです。こちらは中間テーブルとなります。
上記を例にすると、Recipeテーブル、Ingredientテーブルがあり、それをRecipe_Ingredientで紐づけるイメージです。
ということでCakePHP2.xのアソシエーションについてメモしました。
皆さんもご存知の通りすでにCakePHPは3系がリリースされています。
自分はこれから3系についても勉強をしていきますが、ファイル構成を眺めただけでも大分2系とは違いがありそうです。
ですがきっとこれまで勉強していた2系がベースとして役立つと思います。
新しい技術習得に努めていきたいと思います。
間違っていることや分かりやすい考え方、3系での違い等の情報があれば、ぜひコメントを残していただけると嬉しいです。
よろしくお願い致します。m(_ _)m