【CakePHP2】HABTMモデルの練習
いくつか CakePHP でコンテンツを作成してきたのですが、HABTM(HasAndBelongsToMany)を利用したリレーションを作成したことがなかったので、どんなものなのか作成してみました。
HABTMで検索し、blogですかい さんで紹介されていたアニメと声優の関係を作成するというケースがなかなか分かりやすかったので、それに挑戦してみました。
CakePHPの「HABTM」作成
テーブル作成
今回は
- animes テーブル
- voiceactors テーブル
- animes_voiceactors テーブル
の3つのテーブルを用意します。
[]
↑ ER図もどき
肝は「animes_voiceactors」テーブル。
テーブルの命名規則でアルファベット順、どちらも複数形のテーブル名を付ける必要があります。
アルファベット順が逆になる「voiceactors_animes」テーブルでは「テーブルが無いよ!」というエラーが出ます。
ではチャチャッとテーブルをSQLで作成、データを放り込みます。
”atn_”はテスト用につけたプレフィックスです。
animes テーブル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
CREATE TABLE `atn_animes` ( `id` INT UNSIGNED AUTO_INCREMENT, -- `created` DATETIME DEFAULT NULL, -- `modified` DATETIME DEFAULT NULL, -- `delete_flg` TINYINT NOT NULL default '0', -- 削除フラグ `publish_flg` TINYINT NOT NULL default '1', -- 公開フラグ `title` VARCHAR(255), -- タイトル PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `atn_animes` (id, created, modified, delete_flg, publish_flg, title) VALUES (null, NOW(), NOW(), 0, 1, 'うる星やつら'); INSERT INTO `atn_animes` (id, created, modified, delete_flg, publish_flg, title) VALUES (null, NOW(), NOW(), 0, 1, 'シティハンター'); INSERT INTO `atn_animes` (id, created, modified, delete_flg, publish_flg, title) VALUES (null, NOW(), NOW(), 0, 1, 'ハイスクール!奇面組'); INSERT INTO `atn_animes` (id, created, modified, delete_flg, publish_flg, title) VALUES (null, NOW(), NOW(), 0, 1, 'ルパン三世 風魔一族の陰謀'); |
voiceactors テーブル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
CREATE TABLE `atn_voiceactors` ( `id` INT UNSIGNED AUTO_INCREMENT, -- `created` DATETIME DEFAULT NULL, -- `modified` DATETIME DEFAULT NULL, -- `delete_flg` TINYINT NOT NULL default '0', -- 削除フラグ `publish_flg` TINYINT NOT NULL default '1', -- 公開フラグ `name` VARCHAR(255), -- 氏名 PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `atn_voiceactors` (id, created, modified, delete_flg, publish_flg, name) VALUES (null, NOW(), NOW(), 0, 1, '古川 登志夫'); INSERT INTO `atn_voiceactors` (id, created, modified, delete_flg, publish_flg, name) VALUES (null, NOW(), NOW(), 0, 1, '神谷 明'); INSERT INTO `atn_voiceactors` (id, created, modified, delete_flg, publish_flg, name) VALUES (null, NOW(), NOW(), 0, 1, '千葉 繁'); |
animes_voiceactors テーブル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
-- HABTM CREATE TABLE `atn_animes_voiceactors` ( `id` INT UNSIGNED AUTO_INCREMENT, -- `created` DATETIME DEFAULT NULL, -- `modified` DATETIME DEFAULT NULL, -- `delete_flg` TINYINT NOT NULL default '0', -- 削除フラグ `publish_flg` TINYINT NOT NULL default '1', -- 公開フラグ `voiceactor_id` INT NOT NULL, -- `anime_id` INT NOT NULL, -- PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `atn_animes_voiceactors` (id, created, modified, delete_flg, publish_flg, voiceactor_id, anime_id) VALUES (null, NOW(), NOW(), 0, 1, 1, 1); INSERT INTO `atn_animes_voiceactors` (id, created, modified, delete_flg, publish_flg, voiceactor_id, anime_id) VALUES (null, NOW(), NOW(), 0, 1, 1, 4); INSERT INTO `atn_animes_voiceactors` (id, created, modified, delete_flg, publish_flg, voiceactor_id, anime_id) VALUES (null, NOW(), NOW(), 0, 1, 2, 1); INSERT INTO `atn_animes_voiceactors` (id, created, modified, delete_flg, publish_flg, voiceactor_id, anime_id) VALUES (null, NOW(), NOW(), 0, 1, 2, 2); INSERT INTO `atn_animes_voiceactors` (id, created, modified, delete_flg, publish_flg, voiceactor_id, anime_id) VALUES (null, NOW(), NOW(), 0, 1, 3, 1); INSERT INTO `atn_animes_voiceactors` (id, created, modified, delete_flg, publish_flg, voiceactor_id, anime_id) VALUES (null, NOW(), NOW(), 0, 1, 3, 3); |
80年台の香りがプンプンですな(笑)
CakePHPのモデル作成
次にモデルの作成。
- Anime.php
- Voiceactor.php
- AnimesVoiceactor.php
上記3つを用意。
HABTM用のモデルは 前が複数形、後が単数形の単語になるというややこしい命名規則です。
Anime.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php class Anime extends AppModel { public $name = 'Anime'; // アソシエーション public $hasAndBelongsToMany = array( 'Voiceactor' => array( 'className' => 'Voiceactor', 'joinTable' => 'animes_voiceactors', // 中間テーブルの名称(Model名ではなくテーブル名) 'foreignKey' => 'anime_id', // animes_voiceactorsの中のAnimeとのforeignKey 'associationForeignKey' => 'voiceactor_id', // アソシエーションしている中のforeignKey.ここではAnimesVoiceactorのvoiceactor_id 'unique' => true, 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' ) ); } |
Voiceactor.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php class Voiceactor extends AppModel { public $name = 'Voiceactor'; // アソシエーション public $hasAndBelongsToMany = array( 'Anime' => array( 'className' => 'Anime', 'joinTable' => 'animes_voiceactors', // 中間テーブルの名称(Model名ではなくテーブル名) 'foreignKey' => 'voiceactor_id', // animes_voiceactorsの中のVoiceactorとのforeignKey 'associationForeignKey' => 'anime_id', // アソシエーションしている中のforeignKey.ここではAnimesVoiceactorのanime_id 'unique' => true, 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' ) ); } |
AnimesVoiceactor.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php class AnimesVoiceactor extends AppModel { public $name = 'AnimesVoiceactor'; // アソシエーション public $belongsTo = array( 'Anime' => array( 'className' => 'Anime', 'foreignKey' => 'anime_id', 'dependent' => false, 'conditions' => '', 'fields' => '', 'order' => '', ), 'Voiceactor' => array( 'className' => 'Voiceactor', 'foreignKey' => 'voiceactor_id', 'dependent' => false, 'conditions' => '', 'fields' => '', 'order' => '', ), ); } |
CakePHPの「HABTM」結果
Anime一覧
Anime一覧のデバッグ
1 2 3 4 5 6 7 8 9 |
// Anime一覧取得 $anime_data = $this->Anime->find( 'all', array( 'conditions' => array('Anime.publish_flg' => 1), 'fields' => null, 'order' => array('Anime.id' => 'ASC'), 'recursive' => 1 ) ); |
HABTM設定前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
Array ( [0] => Array ( [Anime] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら ) ) [1] => Array ( [Anime] => Array ( [id] => 2 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => シティハンター ) ) [2] => Array ( [Anime] => Array ( [id] => 3 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ハイスクール!奇面組 ) ) [3] => Array ( [Anime] => Array ( [id] => 4 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ルパン三世 風魔一族の陰謀 ) ) ) |
AnimeモデルのHABTM設定後
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
Array ( [0] => Array ( [Anime] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら ) [Voiceactor] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 古川 登志夫 [AnimesVoiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 1 ) ) [1] => Array ( [id] => 2 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 神谷 明 [AnimesVoiceactor] => Array ( [id] => 3 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 2 [anime_id] => 1 ) ) [2] => Array ( [id] => 3 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 千葉 繁 [AnimesVoiceactor] => Array ( [id] => 5 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 3 [anime_id] => 1 ) ) ) ) [1] => Array ( [Anime] => Array ( [id] => 2 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => シティハンター ) [Voiceactor] => Array ( [0] => Array ( [id] => 2 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 神谷 明 [AnimesVoiceactor] => Array ( [id] => 4 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 2 [anime_id] => 2 ) ) ) ) [2] => Array ( [Anime] => Array ( [id] => 3 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ハイスクール!奇面組 ) [Voiceactor] => Array ( [0] => Array ( [id] => 3 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 千葉 繁 [AnimesVoiceactor] => Array ( [id] => 6 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 3 [anime_id] => 3 ) ) ) ) [3] => Array ( [Anime] => Array ( [id] => 4 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ルパン三世 風魔一族の陰謀 ) [Voiceactor] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 古川 登志夫 [AnimesVoiceactor] => Array ( [id] => 2 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 4 ) ) ) ) ) |
Anime詳細
Anime詳細のデバッグ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
Array ( [Anime] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら ) [Voiceactor] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 古川 登志夫 [AnimesVoiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 1 ) ) [1] => Array ( [id] => 2 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 神谷 明 [AnimesVoiceactor] => Array ( [id] => 3 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 2 [anime_id] => 1 ) ) [2] => Array ( [id] => 3 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 千葉 繁 [AnimesVoiceactor] => Array ( [id] => 5 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 3 [anime_id] => 1 ) ) ) ) |
Voiceactor一覧
Voiceactor一覧のデバッグ
1 2 3 4 5 6 7 8 9 |
// Voiceactor一覧取得 $voiceactor_data = $this->Voiceactor->find( 'all', array( 'conditions' => array('Voiceactor.publish_flg' => 1), 'fields' => null, 'order' => array('Voiceactor.id' => 'ASC'), 'recursive' => 1 ) ); |
HABTM設定前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
Array ( [0] => Array ( [Voiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 古川 登志夫 ) ) [1] => Array ( [Voiceactor] => Array ( [id] => 2 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 神谷 明 ) ) [2] => Array ( [Voiceactor] => Array ( [id] => 3 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 千葉 繁 ) ) ) |
VoiceactorモデルのHABTM設定後
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
Array ( [0] => Array ( [Voiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 古川 登志夫 ) [Anime] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら [AnimesVoiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 1 ) ) [1] => Array ( [id] => 4 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ルパン三世 風魔一族の陰謀 [AnimesVoiceactor] => Array ( [id] => 2 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 4 ) ) ) ) [1] => Array ( [Voiceactor] => Array ( [id] => 2 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 神谷 明 ) [Anime] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら [AnimesVoiceactor] => Array ( [id] => 3 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 2 [anime_id] => 1 ) ) [1] => Array ( [id] => 2 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => シティハンター [AnimesVoiceactor] => Array ( [id] => 4 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 2 [anime_id] => 2 ) ) ) ) [2] => Array ( [Voiceactor] => Array ( [id] => 3 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 千葉 繁 ) [Anime] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら [AnimesVoiceactor] => Array ( [id] => 5 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 3 [anime_id] => 1 ) ) [1] => Array ( [id] => 3 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ハイスクール!奇面組 [AnimesVoiceactor] => Array ( [id] => 6 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 3 [anime_id] => 3 ) ) ) ) ) |
Voiceactor詳細
Voiceactor詳細のデバッグ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
Array ( [Voiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:16:36 [modified] => 2015-03-12 17:16:36 [delete_flg] => 0 [publish_flg] => 1 [name] => 古川 登志夫 ) [Anime] => Array ( [0] => Array ( [id] => 1 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => うる星やつら [AnimesVoiceactor] => Array ( [id] => 1 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 1 ) ) [1] => Array ( [id] => 4 [created] => 2015-03-12 17:21:25 [modified] => 2015-03-12 17:21:25 [delete_flg] => 0 [publish_flg] => 1 [title] => ルパン三世 風魔一族の陰謀 [AnimesVoiceactor] => Array ( [id] => 2 [created] => 2015-03-12 17:21:55 [modified] => 2015-03-12 17:21:55 [delete_flg] => 0 [publish_flg] => 1 [voiceactor_id] => 1 [anime_id] => 4 ) ) ) ) |
各レコードの取得に際しての recursive 値は 1 ですが、HABTM設定後はいい具合にリレーションして取得していますね。
モデルさえきちんと設定できればあまり何も考えずに必要レコードを引っ張ってきてくれるので、なかなか便利な設定ではないでしょうか。
参考にしたサイト様
CakePHP2でHABTMなモデルを作った話 - blogですかい