【发布时间】:2013-03-13 16:50:44
【问题描述】:
为什么 cakePHP 不将我的所有关联都包含在一个 SQL 查询中?我能够做到这一点的唯一方法是使用“加入”,但我希望 belongsTo 和 Containable 行为就足够了。
这是一个例子: Post->belongsTo->Category->belongsTo->category_type (所有模型均已正确设置并正常工作。
在索引中列出带有分页的帖子,我试试这个:
public function index() {
$this->paginate = array( 'contain' => array('Category' => array('CategoryType')));
$this->set('posts', $this->paginate());
}
这会正确地获取数组,但它在许多 SQL 中都是这样的:
SELECT `Post`.`id`, `Post`.`name`, `Post`.`content`, `Post`.`category_id`, `Category`.`id`, `Category`.`name`, `Category`.`category_type_id` FROM `unit_app`.`post` AS `Post` LEFT JOIN `unit_app`.`categories` AS `Category` ON (`Post`.`category_id` = `Category`.`id`) WHERE 1 = 1 LIMIT 20
SELECT `CategoryType`.`id`, `CategoryType`.`name` FROM `unit_app`.`category_types` AS `CategoryType` WHERE `CategoryType`.`id` = 1
SELECT `CategoryType`.`id`, `CategoryType`.`name` FROM `unit_app`.`category_types` AS `CategoryType` WHERE `CategoryType`.`id` = 2
SELECT `CategoryType`.`id`, `CategoryType`.`name` FROM `unit_app`.`category_types` AS `CategoryType` WHERE `CategoryType`.`id` = 2
这使得在 CategoryType.name ASC 上对该查询进行排序变得困难。 有什么建议吗?
如果连接是唯一的选择,我是否必须在查询之前取消绑定模型? 分页可以与连接一起正常工作吗?
注意!这只是所有模型的一小部分,生成的 post->index 还需要通过类似的关联获取许多其他模型。
(在 cake 2.2.0 和 v2.4.0-dev、php v5.4.11 上测试)
更新! ---------
我只是想展示我的发现。我现在已经在没有连接的情况下解决了这个问题,但我必须在模型中重新绑定才能使其正常工作。
这基本上是我为使其工作所做的工作(也包括分页和排序): 在 Post 模型中: 添加绑定功能:
$this->unbindModel(array(
'belongsTo' => array('Category')
));
$this->bindModel(array(
'hasOne' => array(
'Category' => array(
'foreignKey' => false,
'conditions' => array('Category.id = Post.category_id')
),
'CategoryType' => array(
'foreignKey' => false,
'conditions' => array('CategoryType.id = Category.category_type_id')
))));
然后我将其添加到 Post 控制器中的索引中:
$this->Post->bindCategory();
$this->paginate = array('contain' => array('Category' ,'CategoryType'));
$this->set('posts', $this->paginate());
我也包含表格标题,仅用于文档:
<th><?php echo $this->Paginator->sort('CategoryType.name', 'Type'); ?></th>
<th><?php echo $this->Paginator->sort('Category.name', 'Category'); ?></th>
我希望这篇文章也可以帮助其他人:)
我还将测试此行为,看看我是否也可以省略所有绑定函数:https://github.com/siran/linkable/
蛋糕有很多插件,但蛋糕应该有插件的“认证”。在 github 上很难找到完全正常工作和测试过的 :)
我也想念 railscasts.com 这样的网站,只是为了蛋糕 :D
/MartOn
【问题讨论】:
-
我同意你的观点,CakePHP 并不总是生成有效的查询。但是,我想知道其他 ORM 框架是否在这方面做得更好。最后,分析生成的 SQL 语句并(如果需要)尝试优化它们是一种很好的做法(就像您所做的那样)。我特别提到了如果需要,因为有时它真的取决于执行查询的频率,而优化至关重要。对于非常复杂的关系,可以使用自定义(原始 SQL)查询,但只能作为最后的手段。
-
在这些情况下更简洁的解决方案是将您的(复杂)查询包装在“数据库视图”(
CREATE VIEW post_with_category AS ...并将其用作模型的数据库源。这样您的 CakePHP 模型可以保持简单,数据库视图将充当“抽象层”。dev.mysql.com/doc/refman/5.0/en/create-view.htmlIMO 尽可能尝试使用 CakePHP 查询,但如果事情变得如此复杂,请不要强迫自己使用它们它只会让你的代码更难理解和维护。
标签: cakephp