我有3个模型,Page
, Course
and Content
Page
and Course
包含元数据和Content
包含 HTML 内容。
Page
and Course
两者都有很多Content
Content
属于Page
and Course
为了避免有page_id
and course_id
领域在Content
(因为我希望它扩展到超过 2 个模型)我正在考虑使用多态关联。我开始使用多态行为 http://bakery.cakephp.org/articles/AD7six/2008/03/13/polymorphic-behavior在 Bakery 中,但它生成了太多我喜欢的 SQL 查询,并且还抛出了“非法偏移”错误,我不知道如何修复该错误(它是 2008 年编写的,最近似乎没有人提到过它,所以也许错误是因为它不是为 Cake 2 设计的?)
不管怎样,我发现我几乎可以通过对模型中的关联进行硬编码来完成我需要的一切,如下所示:
页面模型
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')
)
);
}
?>
好处是$this->Content->find('first')
只生成一个 SQL 查询,而不是 3 个(与多态行为的情况一样),但问题是返回的数据集包括两个 ownTo 模型,而它应该只返回存在的模型。返回的数据如下所示:
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'
)
)
我只希望它返回其中之一Page
or Course
取决于 Content.class 中指定的哪一个
UPDATE:结合Page
and Course
模型似乎是这个问题的明显解决方案,但我上面显示的模式只是为了解决这个问题而显示的。实际模式实际上在其领域方面非常不同,并且每个模式与其他模型也有不同数量的关联。
UPDATE 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