Cakephp分页按计算字段排序(COUNT)
在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
也许您的问题可以使用 虚拟字段 解决?
如果您为计算字段创建自定义字段,您将能够在该自定义字段上使用 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).
您可能想要做的是在您的应用程序中使用 Cake 的 counterCache 功能模型定义。您无需在阅读时计算评论计数,而是将
nbr_comments
添加为articles
表中的 int 字段。每次插入或删除Comment
时,nbr_comments
都会自动更新。在您的
Comment
模型中:现在您只需使用
$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 yourarticles
table. Every time aComment
is inserted or deleted,nbr_comments
will be updated automatically.In your
Comment
model:Now you can just use
$this->Paginator->sort('Article.nbr_comments');
You wont need to do anything funky in your controller.我对此问题的解决方案如下:
将计算字段作为虚拟字段,
然后,您可以在分页顺序变量中使用该字段
My solution for this problem was the following:
put your calculate field as a virtual field
then, you can use that field, in your paginate order variable