Как я могу сделать заказ по «голосам» в CakePHP? - PullRequest
4 голосов
/ 18 апреля 2011

Я использую CakePHP для CMS / веб-службы для питания приложения iPhone.Мне интересно, как бы я упорядочил свой метод .find (), чтобы я мог упорядочить по «количеству» некоторых внешних моделей?

Например: объект video ассоциируется с голосами .Таким образом, существует несколько строк голосования (с user_id и video_id) для одной строки видео.

$videos = $this->Video->find('list', array( <<orderby stuff>> ));

Как изменить предложение orderby, чтобы оно возвращало 25 самых популярных видео по голосам

Ответы [ 2 ]

1 голос
/ 18 апреля 2011

Предположим, у вас есть следующие таблицы:

CREATE TABLE `videos` (
  `id` char(36) NOT NULL,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
)

CREATE TABLE `votes` (
  `id` char(36) NOT NULL,
  `video_id` char(36) NOT NULL,
  `user_id` char(36) NOT NULL,
  PRIMARY KEY (`id`)
);

SQL, который вы пытаетесь написать, выглядит примерно так:

    SELECT 
      count(id), 
      video_id 
   FROM votes 
   GROUP BY video_id 
   ORDER BY count(id) DESC 
   LIMIT 25;

Проблема в том, что видео не будет возвращеноназвание.Это легко исправить с помощью JOIN или с помощью рекурсивной функции тортов.Учитывая вышесказанное, я бы написал следующее:

$this->Vote->recursive = 1;
$vote_info = $this->Vote->find('all', 
   array(
      'fields' => array('count(Vote.id)','Video.name'), 
      'group' => array('video_id'), 
      'order' => array('count(Vote.id) DESC'), 
      'limit' => 25, 
   )
);

Когда вы вернете данные, вы также получите информацию о видео (поскольку для рекурсивного параметра установлено значение 1), если ваши отношения вмодели настроены правильно.

Например, данные будут выглядеть примерно так:

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [count(`Vote`.`id`)] => 3
                )
            [Video] => Array
                (
                    [name] => Dumb and Dumber
                )
        )
    [1] => Array
        (
            [0] => Array
                (
                    [count(`Vote`.`id`)] => 1
                )
            [Video] => Array
                (
                    [name] => Lord of the Rings
                )
        )
    [2] => Array
        (
            [0] => Array
                (
                    [count(`Vote`.`id`)] => 1
                )
            [Video] => Array
                (
                    [name] => Just Do It
                )
        )
)

Я думаю, что отсюда видно, как получить доступ к данным в вашем представлении.

Hoppy Coding!

ОБНОВЛЕНИЕ: Если вам нужен только идентификатор видео, вы можете сделать что-то вроде:

$this->Vote->recursive = 0;
$votes = $this->Vote->find('all', 
   array(
      'fields' => array('count(Vote.id) as count', 'Vote.video_id'), 
      'order' => array('count(Vote.id) DESC'),
      'group' => array('Vote.video_id'),
      'limit' => 25,
   )
);

Это вернет:

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [count] => 3
                )
            [Vote] => Array
                (
                    [video_id] => 4dac4de7-4f80-48c1-8a02-83b4dfa458e5
                )
        )
    [1] => Array
        (
            [0] => Array
                (
                    [count] => 1
                )
            [Vote] => Array
                (
                    [video_id] => 4dac4ddc-712c-4795-8d9a-83b4dfa458e5
                )
        )
    [2] => Array
        (
            [0] => Array
                (
                    [count] => 1
                )
            [Vote] => Array
                (
                    [video_id] => 4dac4df0-382c-4bb5-a5ee-83b4dfa458e5
                )
        )
)
1 голос
/ 18 апреля 2011

Комментарий Данхамзза об использовании counterCache (+1) - лучший подход.После того, как вы устанавливаете это каждый раз, когда кто-то добавляет голосование, поле с именем voice_count будет увеличиваться в таблице видео для соответствующего видео.Затем вы можете просто отсортировать по этому полю.

Итак, в вашей модели голосования

var $belongsTo = array('Video' => array('counterCache' =>true));

И создать поле voice_count в вашей таблице видео

Затем отсортировать

$videos = $this->Video->find('list', array( 'order' => array('vote_count DESC'), 'limit'=>25 ))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...