Сортировка страниц CakePHP по вычисляемому полю (COUNT)

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

предположим, что у меня есть две модели: статья и комментарии (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() метод для разбиения на страницы с помощью группы 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>

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

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

2 ответов


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

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

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


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

в своем Comment модель:

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

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