CakePHP模型:COUNT(*)in Containable

sib*_*iba 12 php pagination cakephp model

我有一个CakePHP 1.3应用程序,并且非常喜欢用于获取数据的Containable行为.

让我们假设我的帖子与评论有一对多的关系.我使用Containable查询(用于分页)所有帖子和所属的注释的列表.但我只对每个帖子有多少评论感兴趣.我没有找到任何方法来实现这个包含可查询的查询而不获取所有注释行.我试过了:

$this->paginate=array(
            'fields' => 'Post.title, Post.created',
            'contain' => array('Comment'=>'COUNT(*) AS count'),
        );
Run Code Online (Sandbox Code Playgroud)

结果"模型"注释"与模型"计数"错误消息无关.

$this->paginate=array(
            'fields' => array('Post.title, Post.created'),
            'contain' => array('Comment'=>array('fields'=>'COUNT(*) AS count'),
        );
Run Code Online (Sandbox Code Playgroud)

如果不起作用,结果集为每个Post包含一个空的Comment数组,除了最后一个数组,它包含count字段,但是所有注释的数量不仅仅是所属的注释.

我的另一个猜测是

$this->paginate=array(
            'fields' => 'Post.title, Post.created, COUNT(Comment.id)',
            'contain' => array('Comment'=>array('fields'=>''),
        );
Run Code Online (Sandbox Code Playgroud)

但这会导致错误,因为hasMany关系是独立查询的,因此Answer表不在Post条目的查询中.我怎样才能计算帖子的评论数量?

paw*_*ior 11

那么,最好的方法是设置一个comment_countposts表中调用的字段,并将此键添加到Comment模型$ belongsTo Post数组中:

'counterCache' => true

每当评论发生任何事情时,相关帖子中的comment_count字段将被更新(实际上,它每次都会重新计算,而不仅仅是添加或删除).

它更好,因为当您为用户获取数据时,它的速度更快,甚至不会触及评论表.由于您使用的是Containable行为,我认为速度和轻量级是您正在寻找的.

  • 这是一个不错的主意,但它并不能解决更复杂的查询问题,因为保持与行关联的计数不起作用(例如,用户选择某些条件的报告系统).有没有其他方法可以使用可包含的计数? (4认同)

Sun*_*arc 5

我有同样的问题.PawelMysior给出的答案很棒并且导致了解决方案.

我在CakePHP Book中找到了更多细节:3.7.4.1.1 counterCache - 缓存你的计数().这很有帮助,但仍然有点模糊.为了他人,我想提供一些进一步的细节.

我有两个表: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;
Run Code Online (Sandbox Code Playgroud)

请注意,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
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

请注意,它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')
        )
    )
));
Run Code Online (Sandbox Code Playgroud)

现在,当我们执行a时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
                    )
                )
        )
)
Run Code Online (Sandbox Code Playgroud)

有一点需要注意,如果将counterCache添加到现有数据库结构,则计数Post将为零,直到Image添加另一个.此时,CakePHP将进行实际计数并更新image_count为正确的数量.

我希望这些额外的信息对某人有帮助.