如何在CakePHP中的多个表中编写连接查询?

时间:2009-04-30 12:25:31

标签: cakephp join

任何人都可以告诉我,如何从cakePHP中的多个表中检索连接结果(使用cakePHP mvc架构)。例如,我有三个表要加入(tbl_topics,tbl_items,tbl_votes。他们的关系定义如下:一个主题可以有很多项目,一个项目可以有很多选票。现在我想检索一个主题列表,其中包括每个主题的所有项目的所有投票。对此的SQL查询如下:

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())。

6 个答案:

答案 0 :(得分:40)

$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 abele的文章中提到:link text

答案 1 :(得分:2)

我会诚实地说,如果你只是在你的模型中创建一个函数,比如getTopicVotes()和在那里调用query(),你可能会更开心。我能想到的每一个其他解决方案只会让它更复杂,因此更加丑陋。

编辑:

根据您的数据大小,并假设您已正确设置模型关系(主题包含多个项目有多个投票),您可以执行包含所有的简单查找('all')项目和投票,然后做这样的事情:

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

这里有两件事很重要:

  1. 如果你有很多数据,你可能会忘记这种方法,它会很慢。
  2. 我是从记忆中写下来的,在现实生活中可能看起来不像这样,和/或根本不起作用: - )

答案 2 :(得分: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',
    ),
));

答案 3 :(得分:1)

您需要的是递归关联支持,目前使用CakePHP库存是不可能的 虽然可以使用一些bindModel trickery来实现 或实验RecursiveAssociationBehavior

这两种解决方案都要求您使用额外的代码或依赖应用程序中的行为,但如果您不耐写编写纯SQL代码的诱惑,您将获得能够使用Cake的分页奖励,自动条件,模型魔术等。

答案 4 :(得分:0)

我认为这个答案已经提交了,但是我在这里发给那些仍在寻找答案的人。 可以使用如下的find()方法完成连接

$result = $this->ModelName1->find("all",array(
'fields' => array('ModelName1.field_name','Table2.field_names'), // retrieving fileds 
'joins' => array(  // join array
    array(
        'table' => 'table_name',
        'alias' => 'Table2',
        'type' => 'inner',
        'foreignKey' => false,
        'conditions'=> array('ModelName1.id = Table2.id') // joins conditions array
    ),
    array(
        'table' => 'table_name3',
        'alias' => 'Table3',
        'type' => 'inner',
        'foreignKey' => false,
        'conditions'=> array('Table3.id = Table2.id')
    )
))); 

答案 5 :(得分:-2)

你应该学习HaBTM(已经和属于许多人) http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html