我有一个CakePHP 1.3应用程序,非常喜欢Containable behavior来获取数据。
我们假设我的帖子与评论有一对多的关系。我使用Containable查询(用于分页)所有帖子和所属的注释的列表。但我只对每个帖子有多少评论感兴趣。我没有找到任何方法来实现这个包含可查询的查询而不获取所有注释行。我试过了:
$this->paginate=array(
'fields' => 'Post.title, Post.created',
'contain' => array('Comment'=>'COUNT(*) AS count'),
);
导致'模型'注释“与模型”Count“'错误消息无关。
$this->paginate=array(
'fields' => array('Post.title, Post.created'),
'contain' => array('Comment'=>array('fields'=>'COUNT(*) AS count'),
);
不起作用,结果集为每个Post包含一个空的Comment数组,除了最后一个数组,它包含count字段,但是所有注释的数量不仅仅是所有的注释。
我的另一个猜测是
$this->paginate=array(
'fields' => 'Post.title, Post.created, COUNT(Comment.id)',
'contain' => array('Comment'=>array('fields'=>''),
);
但这会导致错误,因为hasMany关系是独立查询的,因此Answer表不在Post条目的查询中。 我怎样才能计算帖子的评论数量?
答案 0 :(得分:12)
嗯,最好的方法是在comment_count
表中设置一个名为posts
的字段,并将此键添加到Comment模型$ belongsTo Post数组中:
'counterCache' => true
每当评论发生任何事情时,相关帖子中的comment_count字段都会更新(实际上,它每次都会重新计算,而不仅仅是添加或删除)。
最好,因为当您为用户获取数据时,它的速度更快,甚至不会触及评论表。由于您使用的是Containable行为,我认为速度和轻量级是您正在寻找的。 p>
答案 1 :(得分:6)
我有同样的问题。 PawelMysior给出的答案非常好,并导致了解决方案。
我在CakePHP Book中找到了更多细节:3.7.4.1.1 counterCache - Cache your count()。这很有帮助,但仍然有点模糊。为了其他人,我想提供一些进一步的细节。
我有两张桌子:Post和Image。当我在帖子中添加图像时,我想跟踪每个帖子在Post索引列表上显示的图像数量,而不需要在Image表上运行额外的计数查询。
CREATE TABLE posts
(
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
user_id INTEGER UNSIGNED NOT NULL,
title VARCHAR(255),
body TEXT,
created DATETIME,
modified DATETIME,
image_count INTEGER UNSIGNED,
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE images
(
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
post_id INTEGER UNSIGNED NOT NULL,
filename VARCHAR(255),
created DATETIME,
modified DATETIME,
PRIMARY KEY (id)
) ENGINE=InnoDB;
请注意,image_count
位于posts
表中。 images
表中没有任何特殊内容。
class Post extends AppModel
{
var $name = 'Memory';
var $hasMany = array(
'Image' => array(
'className' => 'Image',
'foreignKey' => 'post_id',
'dependent' => false
)
);
}
class Image extends AppModel
{
var $name = 'Image';
var $belongsTo = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => 'post_id',
'counterCache' => true
)
);
}
请注意,counterCache
已添加到Image
模型中。 Post
模型中不需要任何特殊内容。
$this->Post->Behaviors->attach('Containable');
$post = $this->Post->find('all', array(
'conditions' => array('user_id' => 7),
'order' => array('Post.created DESC'),
'contain' => array(
'Post' => array(
'User' => array('first_name', 'last_name')
)
)
));
现在,当我们执行find
时,无需执行任何特殊操作来查找计数,因为它自动成为Post
结果中的字段。请注意下面的image_count
。
Array
(
[Post] => Array
(
[0] => Array
(
[id] => 14
[user_id] => 7
[title] => Another great post
[body] => Lorem ipsum...
[created] => 2011-10-26 11:45:05
[modified] => 2011-10-26 11:45:05
[image_count] => 21
[User] => Array
(
[first_name] => John
[last_name] => Doe
)
)
)
)
需要注意的一点是,如果将counterCache添加到现有数据库结构中,Post
中的计数将为零,直到添加另一个Image
为止。此时,CakePHP将进行实际计数并将image_count
更新为正确的数量。
我希望这些额外的信息对某人有用。