【发布时间】:2011-11-22 12:10:20
【问题描述】:
我尝试在 CakePHP 中使用 Containable Behavior 已经有一段时间了,但我无法让它按预期工作。
我的应用程序不同,但为了简化,我将举这个例子。假设我有一个包含主题和活动的论坛,并且可以对活动进行评级。一般关系是:
论坛:hasMany [主题]
主题:belongsTo [论坛]、hasMany [活动]
活动:belongsTo [Thread]、hasMany [Rating]
评分:属于 [Activity]
我想要实现的是,使用 find 方法,获取在某个论坛上执行的所有评级。我认为应该做的是:
$this->Rating->find('count', array(
'contain' => array(
'Activity' => array(
'Thread'
)
),
'conditions' => array(
'Thread.forum_id' => 1
)
));
但是查询结果是:
SELECT COUNT(*) AS `count` FROM `ratings` AS `Rating` LEFT JOIN `activities` AS `Activity` ON (`Rating`.`activity_id` = `Activity`.`id`) WHERE `Thread`.`forum_id` = 1;
我已经使用 'joins' 选项完成了这项工作,但它更复杂,而且我必须在许多情况下使用这种操作。
与示例相关的所有文件都可以在这里找到:http://dl.dropbox.com/u/3285746/StackOverflow-ContainableBehavior.rar
谢谢
2011 年 11 月 23 日更新
在调查了框架后,感谢 Moz Morris 和 api55 的回答,我找到了问题的根源。
基本问题是,根据我对 CakePHP 的理解,我认为它每次都使用连接进行查询。它不这样做的事情,它为获得我正在寻找的结果而执行的实际操作将是这样的:
SELECT * FROM Rating JOIN Activity...
SELECT * FROM Activity JOIN Thread...
SELECT * FROM Activity JOIN Thread...
...
这意味着它将执行查询以获取所有活动,然后针对每个活动执行查询以获取线程...我的方法失败不是因为可包含行为被错误使用,而是因为' conditions 选项应用于所有查询,在第一个查询中,由于缺少 Thread 表而崩溃。找出来后,有两种可能的解决方案:
正如 api55 所说,使用 'contain' 数组中的条件只会将它们应用于使用 Thread 表的查询。但是这样做问题仍然存在,因为我们的查询太多了。
正如 Moz Morris 所说,将 Thread 模型绑定到 Rating 也可以,它会执行单个查询,这正是我们想要的。问题是我认为这是一个跳过模型之间关系并且不遵循 CakePHP 哲学的补丁。
我将 api55 解决方案标记为正确,因为它解决了我遇到的具体问题,但两者都给出了问题的解决方案。
【问题讨论】: