Сортировка по Cakephp по вычисляемому полю (COUNT) - PullRequest
6 голосов
/ 16 мая 2011

У меня была проблема с сортировкой разбитого на страницы списка при использовании вычисляемого поля, такого как COUNT (), в cakephp 1.3

Допустим, у меня есть две модели: Article и Comments (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>

И это работает .. но, похоже, слишком много кода длято, что должно быть прозрачным для разработчика.(Такое ощущение, что я делаю торт). Поэтому я спрашиваю, есть ли другой более простой способ.Может быть, торт имеет такую ​​функциональность, но решил спрятать ее ... о_О ... в документации ничего об этом нет, и я не нашел другого хорошего решения по SO .. как ты это делаешь?

Спасибо взаранее!

Ответы [ 2 ]

6 голосов
/ 25 августа 2011

возможно, ваша проблема может быть решена с помощью Виртуальные поля ?

Если вы создадите настраиваемое поле для своего вычисляемого поля, вы сможете сортировать, используя метод Paginator-> sort ()в этом настраиваемом поле.

Я нашел это решение там в комментариях (нет необходимости настраивать метод paginate и т. д. с использованием настраиваемых полей вместо исходного решения adnan).

2 голосов
/ 16 мая 2011

То, что вы можете сделать, это использовать функциональность Cake counterCache в определении вашей модели. Вместо того, чтобы рассчитывать количество комментариев во время чтения, вы добавляете nbr_comments в качестве поля int в таблицу articles. Каждый раз, когда Comment вставляется или удаляется, nbr_comments будет обновляться автоматически.

В вашей Comment модели:

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

Теперь вы можете просто использовать $this->Paginator->sort('Article.nbr_comments'); Вам не нужно делать ничего интересного в вашем контроллере.

...