私は 3 つのモデルを持っていPage
ますCourse
。Content
Page
Course
メタデータを含み、 Content
HTML コンテンツを含みます。
Page
そしてCourse
両方ともhasManyContent
Content
所属先Page
とCourse
フィールドが含まれないようにするためにpage_id
(これを 2 つ以上のモデルに拡張したいため)、ポリモーフィック アソシエーションの使用を検討しています。ベーカリーでポリモーフィック ビヘイビアを使用することから始めましたが、好みの SQL クエリが生成されすぎて、修正方法がわからない「不正なオフセット」エラーがスローされます (これは 2008 年に作成されたもので、誰もそのようには見えません)。最近参照したので、エラーは Cake 2 用に設計されていないことが原因でしょうか?)course_id
Content
とにかく、モデルの関連付けを次のようにハードコーディングすることで、必要なことはほとんどすべてできることがわかりました。
ページ モデル
CREATE TABLE `pages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`)
)
<?php
class Page extends AppModel {
var $name = 'Page';
var $hasMany = array(
'Content' => array(
'className' => 'Content',
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Page'),
)
);
}
?>
コースモデル
CREATE TABLE `courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`)
)
<?php
class Course extends AppModel {
var $name = 'Course';
var $hasMany = array(
'Content' => array(
'className' => 'Content',
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Course'),
)
);
}
?>
コンテンツ モデル
CREATE TABLE IF NOT EXISTS `contents` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`class` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`foreign_id` int(11) unsigned NOT NULL,
`title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`content` text COLLATE utf8_unicode_ci NOT NULL,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
)
<?php
class Content extends AppModel {
var $name = 'Content';
var $belongsTo = array(
'Page' => array(
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Page')
),
'Course' => array(
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Course')
)
);
}
?>
(ポリモーフィック動作の場合のように) 3 つではなく単一の SQL クエリのみを生成することは良いことですが$this->Content->find('first')
、返されるデータセットには両方の属しているモデルが含まれているのに対し、実際には存在するモデルのみを返す必要があるという問題があります。返されるデータは次のようになります。
array(
'Content' => array(
'id' => '1',
'class' => 'Course',
'foreign_id' => '1',
'title' => 'something about this course',
'content' => 'The content here',
'created' => null,
'modified' => null
),
'Page' => array(
'id' => null,
'title' => null,
'slug' => null,
'created' => null,
'updated' => null
),
'Course' => array(
'id' => '1',
'title' => 'Course name',
'slug' => 'name-of-the-course',
'created' => '2012-10-11 00:00:00',
'updated' => '2012-10-11 00:00:00'
)
)
どちらか、またはContent.class で指定されているものに応じて、いずれかを返すだけにしPage
たいCourse
更新:Page
とモデルを組み合わせることはCourse
、この問題の明らかな解決策のように思えますが、上で示したスキーマは、この質問の目的のために示されているだけです。実際のスキーマは実際にはフィールドの点で非常に異なり、それぞれが他のモデルとの関連付けの数も異なります。
更新 2
を実行した結果のクエリを次に示します$this->Content->find('first');
。
SELECT `Content`.`id`, `Content`.`class`, `Content`.`foreign_id`, `Content`.`title`,
`Content`.`slug`, `Content`.`content`, `Content`.`created`, `Content`.`modified`,
`Page`.`id`, `Page`.`title`, `Page`.`slug`, `Page`.`created`, `Page`.`updated`,
`Course`.`id`, `Course`.`title`, `Course`.`slug`, `Course`.`created`,
`Course`.`updated` FROM `cakedb`.`contents` AS `Content`
LEFT JOIN `cakedb`.`pages` AS `Page` ON
(`Content`.`foreign_id` = `Page`.`id` AND `Content`.`class` = 'Page')
LEFT JOIN `cakedb`.`courses` AS `Course` ON (`Content`.`foreign_id` = `Course`.`id`
AND `Content`.`class` = 'Course') WHERE 1 = 1 LIMIT 1