【问题标题】:Cakephp model associastionCakephp 模型关联
【发布时间】:2010-10-11 18:40:09
【问题描述】:

我有你下面的简单模型:

  • 项目属于目录项目
  • CatalogItem 有很多项,并且属于部分
  • Section hasMany CatalogItem
  • 我正在尝试获取某个部分的项目计数,按目录项分组 - 相当于:

    SELECT catalogitem.id, count(*) FROM section LEFT JOIN catalogitem ON section.id=catalogitem.section_id LEFT JOIN item ON item.catalogitem_id=catalogitem.id WHERE section.id=5 GROUP BY catalogitem.id

    在 sql 中如此简单,但我无法让它与蛋糕模型一起使用。谁能指出如何使用模型->查找来处理蛋糕模型? 我无法正确分组或在 3 个表上正确加入:(

    编辑: 非常喜欢在单个查询中获取信息

    【问题讨论】:

      标签: mysql cakephp


      【解决方案1】:

      这是一种更长的方式,“蛋糕”方式:

      class Item extends AppModel
      {
          /* snip */
          var $virtualFields = array('item_count' => 'count(Item.id)');
      
          function getCountForSection($sectionId)
          {
              $ca = $this->Catalogitem->find
                  (
                      'all',
                      array
                      (
                          'fields' => array('Catalogitem.id'),
                          'conditions' => array('Catalogitem.section_id' => $sectionId),
                          'recursive' => -1
                      )
                  );
      
              $ca = Set::extract('/Catalogitem/id', $ca);
      
              $ret = $this->find
                  (
                      'all',
                      array
                      (
                          'fields' => array('Item.catalogitem_id', 'item_count'),
                          'conditions' => array('Item.catalogitem_id' => $ca),
                          'group' => array('Item.catalogitem_id'),
                          'recursive' => -1
                      )
                  );
      
              return $ret;
          }
      }
      

      然后简单地在你的控制器中使用它:

      $ret = $this->Item->getCountForSection(1);
      debug($ret);
      

      它是如何工作的:

      • 定义一个 virtual field(仅 AFAIK 蛋糕 1.3+),它将计算项目数
      • 获取属于您感兴趣的部分的所有目录项
      • 使用Set::extract() 获取简单数组中的目录项
      • 使用 Catalogitems 数组过滤项目,同时对它们进行计数和分组

      注意:您的数据库中似乎没有使用Cake's naming conventions。这可能会伤害你。

      【讨论】:

      • 谢谢汉尼拔!但是,这涉及 2 个查询。
      • 是的,这是两个查询,但这是我短时间内能做的最好的事情。我可能会这样做,并且只有在我发现它会导致性能问题时才对其进行优化。您的第二条评论是什么意思?
      【解决方案2】:

      对不起,在我的第一个答案中,我不知何故错过了您的 GROUP BY 要求,这是问题的全部意义,我现在意识到。我还没有使用它,但我最近遇到了它,它看起来可能会完成您正在寻找的东西:可链接行为。

      http://planetcakephp.org/aggregator/items/891-linkable-behavior-taking-it-easy-in-your-db

      类似于 Containable,但仅适用于右连接和左连接,产生更紧凑的查询并支持 GROUP BY。

      http://github.com/rafaelbandeira3/linkable

      【讨论】:

        【解决方案3】:

        @azv

        这对你有用吗:

        $section_id = 5;
        $fields     = array('CatalogItem.id as CatalogItemId', 'count(*) AS SectionCount');
        $conditions = array('Section.id' => $section_id);
        $joins      = array(
            array('table' => 'catalogitem',
                  'alias' => 'CatalogItem',
                  'type' => 'LEFT',
                  'conditions' => array('Section.id' => 'CatalogItem.section_id')
            ),
            array('table' => 'item',
                  'alias' => 'Item',
                  'type' => 'LEFT',
                  'conditions' => array('Item.catalogitem_id' => 'CatalogItem.id')
        ));
        
        $data = $this->Section->find('all',
                          array('fields' => $fields,
                                'conditions' => $conditions,
                                'joins' => $joins,
                                'group' => 'CatalogItem.id',
                                'recursive' => -1)
                 );
        
        // access your data values
        foreach ($data['Section'] as $i => $datarow) {
            $catalogitem_id = $datarow['CatalogItemId'];
            $section_count  = $datarow['SectionCount'];
        }
        

        通过这种方式,您可以显式设置连接并在一个查询中完成所有操作。有关 Cake 中连接的更多信息,请参见此处:

        http://book.cakephp.org/view/1047/Joining-tables

        希望这会有所帮助。万事如意,
        -s_r

        【讨论】:

        • PS - 我在我的代码中假设您在 sections 控制器中。要在 Section 模型中执行相同操作,请使用 $this->find() 而不是 $this->Section->find()
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多