Cakephp按计算字段分页排序(COUNT)

5hcedyr0  于 2022-11-11  发布在  PHP
关注(0)|答案(3)|浏览(166)

在cakephp 1.3中使用计算字段(如COUNT())时,对分页列表进行排序时遇到了问题
假设我有两个模型:文章和评论(1篇文章x N条评论),我想显示一个分页的文章列表,包括每一篇文章的评论数。我会有这样的东西:

控制器:

$this->paginate = array('limit'=>80,
                        'recursive'=>-1,
                        'fields'=>array("Article.*","COUNT(Comment.id) as nbr_comments"),
                        'joins'=>array(array(   'table' => 'comments',
                                                    'alias' => 'Comment',
                                                    'type' => 'LEFT',
                                                    'conditions' => array('Comment.article_id = Article.id'))
                                            ),
                        'group'=>"Article.id"
                        );

(我必须覆盖findCount()方法,以便使用group by进行分页)
问题在于,在视图中,sort()方法不起作用:

<th><?php echo $this->Paginator->sort('nbr_comments');?></th> //life is not that easy

我能够通过“欺骗”分页和排序来创建一个变通方案:

控制器

$order = "Article.title";
$direction = "asc";
if(isset($this->passedArgs['sort']) && $this->passedArgs['sort']=="nbr_comments")
    $order = $this->passedArgs['sort'];
    $direction = $this->passedArgs['direction'];
    unset($this->passedArgs['sort']);
    unset($this->passedArgs['direction']);
}
$this->paginate = array(... 'order'=>$order." ".$direction, ...);
$this->set('articles', $this->paginate());
if($order == "clicks"){
    $this->passedArgs['sort'] = $order;
    $this->passedArgs['direction'] = $direction;
}

检视

<?php $direction = (isset($this->passedArgs['direction']) && isset($this->passedArgs['sort']) && $this->passedArgs['sort'] == "nbr_comments" && $this->passedArgs['direction'] == "desc")?"asc":"desc";?>
<th><?php echo $this->Paginator->sort('Hits','clicks',array('direction'=>$direction));?></th>

它是可行的..但是看起来代码太多了,对于开发者来说应该是透明的。(感觉就像我在做cake的工作)所以我想问是否有另一种更简单的方法。也许cake有这个功能,但是决定隐藏它.. o_O..文档中没有关于这个的内容,我也没有在S.O.上找到另一种好的解决方案..你怎么做?
提前感谢!

xmq68pz9

xmq68pz91#

也许你的问题可以用Virtual fields来解决?
如果您为计算字段创建了一个自定义字段,您将能够使用Paginator-〉sort()方法对该自定义字段进行排序。
我在注解中发现了there解决方案(不需要使用自定义字段而不是adnan的初始解决方案来自定义分页方法等)。

5q4ezhmt

5q4ezhmt2#

您可能需要在模型定义中使用Cake的counterCache功能。您可以在articles表中添加nbr_comments作为int字段,而不是在读取时计算注解计数。每次插入或删除Comment时,nbr_comments都会自动更新。
在您的Comment模型中:

var $belongsTo = array(
    'Article' => array(
        'counterCache' => 'nbr_comments'
    )
);

现在你可以只使用$this->Paginator->sort('Article.nbr_comments');你不需要做任何时髦的在你的控制器。

h43kikqp

h43kikqp3#

我对这个问题的解决方案如下:
将计算字段设置为虚拟字段

$this->Comment->virtualFields = array(
    'nbr_comments' => 'COUNT(Comment.id)'
);

然后,您可以使用分页顺序变量中字段,

$order = array("Comment.nbr_comments" => "DESC");
$this->Paginator->settings  = array("order" => $order);

相关问题