CakePHP2 中的多态关联

2024-01-30

我有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

你的查询没问题。查找后仅过滤空值:

public function afterFind($results, $primary = false) {
    return Set::filter($results, true);
}

看一眼this https://stackoverflow.com/questions/8289417/cakephp-join-only-if-id-is-not-null问题。

您还可以尝试提供conditions to you find查询那个Page.id不为空or Course.id不为空。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CakePHP2 中的多态关联 的相关文章

随机推荐

  • Linux中如何保护进程间共享的内存

    在 Linux 或其他现代操作系统中 每个进程的内存都受到保护 因此一个进程中的疯狂写入不会导致任何其他进程崩溃 现在假设我们在进程 A 和进程 B 之间共享内存 现在假设 由于软错误 进程 A 无意中向该内存区域写入了一些内容 鉴于进程
  • 如何在 React 中呈现未定义状态的数据?

    我正在 componentDidMount 内获取数据 但在初始渲染期间我未定义 然后再次渲染发生 并且在此期间状态变量被填充 现在 当它不是未定义的并且在填充之后 我想对其进行解构并在我的组件内显示数据 注意 getProjectDeta
  • C++ 中的变量作用域?

    在 C 中 main 中声明的任何变量都可以在整个 main 中使用 对吗 我的意思是 如果变量是在 try 循环中声明的 它们仍然可以在整个 main 中访问吗 因为我在 main 的 try 循环中声明了几个变量 但是如果我在 try
  • 如何获取字典中键的ReadOnlyCollection

    我的课程包含一个Dictionary
  • python time.strftime %z 始终为零而不是时区偏移

    gt gt gt import time gt gt gt t 1440935442 gt gt gt time strftime Y m d H M S z time gmtime t 2015 08 30 11 50 42 0000 g
  • 按实体名称和上次修改日期搜索

    我在 RavenDb 中存储了许多命令 它们都实现了 ICommand 我希望能够搜索上次修改的元数据和 Raven Entity Name 我目前正在对每个命令进行多重映射 如下所示 public class CommandAuditSe
  • 将 PHP 日期范围转换为 MYSQL 单个日期

    我有一个可用性日历 其中我当前正在逐个添加日期 并使用 mysql 查询来确定是否存在具有特定日期的行 并将当天的类别更改为 已预订 红色 我想在我的表单中输入一个范围 并通过 php 或 mysql 将其处理为多个单独的日期 我的日期格式
  • 使用 TensorFlow Dataset API 和 flat_map 的并行线程

    我正在将 TensorFlow 代码从旧的队列接口更改为新的数据集API https www tensorflow org api docs python tf data Dataset 使用旧界面我可以指定num threads论证tf
  • Powershell 检查本地管理员凭据

    我正在尝试运行一个需要管理员输入才能处理某些事情的脚本 我不想让脚本运行失败 而是尝试捕获错误并将其扔回到凭据中 但我找不到可以将本地管理凭据传递给陷阱的命令 有人有什么可能有用的东西吗 我发现很多都会检查域凭据 但这是一个本地管理员帐户
  • Java Swing:显示 JPopupMenu 后插入符侦听器停止触发

    我正在制作一个文本编辑器应用程序 并且遇到了一个问题 在显示 JPopupMenu 后键入或粘贴文本时 我的 CaretListener 不会被触发 我已将 CaretListener 添加到 JTextArea textArea addC
  • 如何为 Next.js API 请求进行 HTTP 代理

    我在网上尝试了很多方法 但到目前为止没有任何效果 第一次尝试 src pages api proxy slug js import createProxyMiddleware from http proxy middleware Creat
  • CommonServiceLocator 的评论中的“环境”一词的含义是什么?

    我想猜测 环境容器 与它是静态类这一事实有关 但这只是一个猜测 或者这是指标准模式 也就是说 我真的需要从头到尾读完 GoF 的书 namespace Microsoft Practices ServiceLocation
  • 为什么 cmpsb 似乎不比较寄存器的值?

    我正在尝试以 16 位实模式编写 DOS 克隆 尽管一旦我完成了当前问题 我可能只会学习 32 位汇编 我的问题过去一直受到负面回应 但这是最后一次 恐怕我确实需要咨询这个网站 改进我之前的问题 我付出了更多努力来了解有关汇编代码中的指针和
  • 如何使用 ffmpeg 降低多个 JPEG 图像文件的质量?

    我想降低当时一堆图像的质量 和 q v x其中 x 是 1 到 30 之间的数字 数字越大 质量越差 即使使用 我也能节省很多空间x 1 现在 当涉及到处理多个文件时 我陷入了困境 我尝试过这两个批处理文件 mkdir processed
  • 获取 Facebook 公共页面评级和评论

    我不是某些页面的所有者 但我想访问页面评论和评级 每次访问时我都会得到空数据集 gt http https graph facebook com 102227700571 tabs reviews access token fb oauth
  • 在 PowerPoint 中从编辑模式下的按钮调用宏

    我正在尝试编写一个可以在 PowerPoint 2007 2010 的编辑模式下调用的 vba 宏 我可以轻松地将命令按钮添加到演示文稿中 但是 只能在幻灯片模式下单击此按钮来触发 vba 宏 但是 我想做的是让此按钮在编辑模式下触发关联的
  • 如何在 Grails 上使用 LDAP 插件?

    我正在开始一个关于 Groovy 和 Grails 的新项目 我现在正在处理身份验证部分 因为我们有一个 LDAP 服务器 所以我想使用 LDAP 进行身份验证 我开始设置我的环境 我正在使用 SpringSource Tool Suite
  • JSP编译期间出现'tmpFile.renameTo(classFile)'的原因

    我正在使用 Jetty 6 服务器 有时会出现此异常 java io IOException tmpFile renameTo classFile failed at org apache jasper compiler SmapUtil
  • 如何知道应用程序是由调试器 (Visual Studio) C# 启动的

    在我的 C 代码中 我想知道应用程序是否已由调试器 在我的例子中为 VisualStudio 启动 有谁知道如何获取这些信息 TIA 系统 诊断 调试器 IsAttached http msdn2 microsoft com en us l
  • CakePHP2 中的多态关联

    我有3个模型 Page Course and Content Page and Course包含元数据和Content包含 HTML 内容 Page and Course两者都有很多Content Content属于Page and Cou