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

发布于 2024-11-07 12:26:28 字数 2323 浏览 7 评论 0原文

在 cakephp 1.3 中使用诸如 COUNT() 之类的计算字段时,我在对分页列表进行排序时遇到问题

假设我有两个模型:文章和评论(1 篇文章 x N 条评论),并且我想显示文章的分页列表包括每条评论的数量。我有这样的东西:

Controller:

$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

我能够通过“欺骗”分页和排序来创建解决方法:

Controller

$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;
}

View

<?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>

并且它有效......但对于开发人员应该透明的东西来说似乎代码太多了。 (感觉就像我在做蛋糕的工作)所以我问是否有另一种更简单的方法。也许蛋糕有这个功能,但决定隐藏它.. o_O .. 文档上没有任何关于此的内容,而且我还没有找到另一个好的解决方案.. 你是怎么做到的?

提前致谢!

I had a problem sorting a paginated list when using a calculated field such as COUNT() in cakephp 1.3

Let's say that i have two models: Article and Comments (1 article x N comments) and i want to display a paginated list of the articles including the number of comments for each one. I'd have something like this:

Controller:

$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"
                        );

(i had to overwrite the findCount() method in order to paginate using group by)

The problem is that in the view, the sort() method won't work:

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

I was able to create a workaround by "cheating" the pagination and sort:

Controller

$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;
}

View

<?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>

And it works.. but it seems that is too much code for something that should be transparent to the developper. (It feels like i'm doing cake's work) So i'm asking if there's another simpler way. Maybe cake has this functionallity but decided to hide it.. o_O.. there's nothing about this on the documentation, and i haven't found another good solution on S.O... how do you do it?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

阳光的暖冬 2024-11-14 12:26:28

也许您的问题可以使用 虚拟字段 解决?

如果您为计算字段创建自定义字段,您将能够在该自定义字段上使用 Paginator->sort() 方法进行排序。

我在评论中找到了解决方案那里 (不需要使用自定义字段而不是在 adnan 的初始解决方案中自定义分页方法等)。

maybe your problem can be solved using Virtual fields ?

If you create a custom field for your computed field, you will be able to sort using Paginator->sort() method on that custom field.

I found that solution there in the comments (there is no need to customize the paginate method etc. using custom fields instead of in adnan's initial solution).

感性不性感 2024-11-14 12:26:28

您可能想要做的是在您的应用程序中使用 Cake 的 counterCache 功能模型定义。您无需在阅读时计算评论计数,而是将 nbr_comments 添加为 articles 表中的 int 字段。每次插入或删除 Comment 时,nbr_comments 都会自动更新。

在您的 Comment 模型中:

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

现在您只需使用 $this->Paginator->sort('Article.nbr_comments'); 您无需在你的控制器。

What you may want to do is use Cake's counterCache functionality in your model definition. Rather than calculating the comment counts at read time, you add nbr_comments as an int field in your articles table. Every time a Comment is inserted or deleted, nbr_comments will be updated automatically.

In your Comment model:

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

Now you can just use $this->Paginator->sort('Article.nbr_comments'); You wont need to do anything funky in your controller.

歌枕肩 2024-11-14 12:26:28

我对此问题的解决方案如下:

将计算字段作为虚拟字段,

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

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

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

My solution for this problem was the following:

put your calculate field as a virtual field

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

then, you can use that field, in your paginate order variable

$order = array("Comment.nbr_comments" => "DESC");
$this->Paginator->settings  = array("order" => $order);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文