代码之家  ›  专栏  ›  技术社区  ›  wojo

如何在cakephp中跨多个表编写连接查询?

  •  15
  • wojo  · 技术社区  · 7 年前

    谁能告诉我,如何在CAKEPHP中使用多个表检索连接结果(使用CAKEPHP MVC架构)。例如,我有三个表要加入(tbl_主题、tbl_项目、tbl_投票)。他们的关系定义如下:一个话题可以有很多项目,一个项目可以有很多选票。现在我要检索一个主题列表,其中包含每个主题的所有项目的所有投票数。下面是对此的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() )

    5 回复  |  直到 12 年前
        1
  •  40
  •   jmcneese    17 年前
    $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'])
            )
        )
    ))); 
    

    内特·阿贝尔的文章中提到: link text

        2
  •  2
  •   dr Hannibal Lecter    17 年前

    老实说,如果您在模型中创建一个函数,比如gettopicvotes()和在那里调用query(),您可能会高兴得多。我能想到的其他解决办法只会使它变得更加复杂,变得更加丑陋。

    编辑:

    根据数据的大小,并假设您已正确设置了模型关系(topic hasmoon items hasmoon vots),您可以执行一个简单的find('all'),其中包含 全部的 项目和投票,然后执行如下操作:

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

    这里有两件事很重要:

    1. 如果你有大量的数据,你可能应该忘记这种方法,它将是地狱般的缓慢。
    2. 我是凭记忆写的,在现实生活中可能看起来不像这样,而且/或者根本不起作用:-)
        3
  •  2
  •   dreamlax    16 年前

    您可以轻松地在FAND()查询上设置“递归”属性。

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

    或者,可以使用模型中的可容纳行为。然后你可以使用:

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

    或

    $result = $this->Topic->find('all', array(
        'contain' => array(
            'Item',
            'Item.Vote',
        ),
    ));
    
        4
  •  1
  •   duckyflip    17 年前

    您需要的是递归关联支持,这在stock-cakephp中是不可能的。
    尽管可以通过使用一些 bindModel trickery
    或是实验性的 RecursiveAssociationBehavior .

    这两种解决方案要么要求您使用额外的代码,要么依赖于应用程序中的某个行为,但是如果您抵制住编写纯sql代码的诱惑,您将获得能够使用cake的分页、自动条件、模型魔术等的奖励。

        5
  •  -2
  •   Matt Michielsen    12 年前