2009-04-30 2 views
14

может кто-нибудь сказать мне, как получить объединенный результат из нескольких таблиц в cakePHP (с использованием mcc-архитектуры cakePHP). Например, у меня есть три таблицы для присоединения (tbl_topics, tbl_items, tbl_votes. Их взаимосвязь определяется следующим образом: в теме может быть много элементов, а элемент может иметь много голосов. Теперь я хочу получить список тем с подсчетом . все голоса по всем пунктам, по каждой теме SQL-запрос для этого написано ниже:Как написать запрос соединения для нескольких таблиц в CakePHP?

SELECT Topic.*, count(Vote.id) voteCount 
FROM 
tbl_topics AS Topic 
LEFT OUTER JOIN tbl_items AS Item 
ON (Topic.id = Item.topic_id) 
LEFT OUTER JOIN tbl_votes AS Vote 
ON (Item.id = Vote.item_id); 

Моя проблема в том, что я могу сделать это легко с помощью $this-><Model Name>->query функции, но для этого требуется код SQL, чтобы записать в контроллер, который я (find())

ответ

2

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

Edit:

В зависимости от размера данных, и если вы создали свои модели отношений надлежащим образом (Тема hasMany товары hasMany Голоса), можно сделать простой находку («все»), содержащий все элементы и голоса, а затем сделать что-то вроде этого:

foreach ($this->data as &$topic) 
{ 
    $votes = Set::extract('/Topic/Item/Vote', $topic); 
    $topic['Topic']['vote_count'] = count($votes); 
} 

Две вещи важны здесь:

  1. Если у вас есть много данных, у возможно, следует забыть об этом подходе, он будет медленным, как черт.
  2. Я написал это из моей памяти, и это не может выглядеть в реальной жизни, и/или он может не работать вообще :-)
-2

Вы должны изучить HABTM (Есть и Принадлежит Many) http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html

+0

Я не понимаю, как это HABTM применяется здесь? –

+0

Попробуйте использовать класс Предмет расширяет AppModel { вар $ belongsTo = массив («Тема») } – drikoda

+0

Не HABTM для двух таблиц, в которых идет речь в вопросе о присоединении трех? – SeanDowney

1

Что вам нужно, это поддержка рекурсивных ассоциаций, что в настоящее время невозможно с запасом CakePHP.
Хотя это может быть достигнуто с использованием некоторых bindModel trickery
или экспериментальных RecursiveAssociationBehavior.

В обоих этих решениях вам потребуется либо использовать дополнительный код, либо полагаться на поведение в вашем приложении, но если вы откажетесь от соблазна написать чистый код SQL, вы получите вознаграждение за возможность использовать разбиение на страницы Cake , автоматические условия, магия модели и т. д.

2

Вы можете легко установить свойство «рекурсивное» в запросе find().

$result = $this->Topic->find('all', array('recursive' => 2)); 

В качестве альтернативы вы можете использовать Containable поведение в своей модели.Затем вы можете использовать:

$this->Topic->contain(array(
    'Item', 
    'Item.Vote', 
)); 

$result = $this->Topic->find('all'); 

или

$result = $this->Topic->find('all', array(
    'contain' => array(
     'Item', 
     'Item.Vote', 
    ), 
)); 
+0

Я пробовал использовать 'содержать', как вы описали, и он не работает. Кроме того, я бы посоветовал использовать 'recursive = 2', потому что, если у вас много ассоциаций, вы забиваете свое приложение. –

+0

@Alex: В моем примере была ошибка. Я починил это. Обязательно добавьте Containable поведение к модели! –

38
$markers = $this->Marker->find('all', array('joins' => array(
    array(
     'table' => 'markers_tags', 
     'alias' => 'MarkersTag', 
     'type' => 'inner', 
     'foreignKey' => false, 
     'conditions'=> array('MarkersTag.marker_id = Marker.id') 
    ), 
    array(
     'table' => 'tags', 
     'alias' => 'Tag', 
     'type' => 'inner', 
     'foreignKey' => false, 
     'conditions'=> array(
      'Tag.id = MarkersTag.tag_id', 
      'Tag.tag' => explode(' ', $this->params['url']['q']) 
     ) 
    ) 
))); 

, как указано в статье Nate ābele в: link text

+0

для большей ясности, пример - просто показать, как вручную добавлять соединения к параметрам model :: find. – jmcneese

+0

im собираюсь проверить это для моих столов сегодня ... – Drewdin

+3

Ваша функция find получает только поля в таблице Marker, а не две другие таблицы. –

Смежные вопросы