【问题标题】:Joining to parent table in CakePHP Model->find()在 CakePHP Model->find() 中加入父表
【发布时间】:2015-03-09 17:29:48
【问题描述】:

我有一个 CakePHP 模型的层次结构,如下所示:

Users > Feedfolders > Feeds > Entries

在 FeedsController 中,我试图根据按 Feed ID 分组的用户 ID 获取所有未读条目的计数。我真的不知道我应该如何以适合 Cake 做事方式的方式来做这件事。我觉得 Cake 基于模型中的 $belongsTo$hasMany 属性对模型的理解应该让它适当地解决连接,但我不确定我做错了什么。我尝试了几个find() 变体,但都没有成功。最近我尝试过:

$result = $this->Feed->find('all', array(
  'conditions' => array('User.id' => $this->Auth->user('id'), 'Entry.read' => 1),
  'fields' => array('count(Entry.feed_id) as Count', 'Entry.feed_id'),
  'group' => 'Entry.feed_id',
  'recursive' => 2)
);

生成以下 SQL:

SELECT count(`Entry`.`feed_id`) as Count, `Entry`.`feed_id`, `Feed`.`id`
FROM `feeds` AS `Feed`
LEFT JOIN `feedfolders` AS `Feedfolder` ON (`Feed`.`feedfolder_id` = `Feedfolder`.`id`)  
WHERE `User`.`id` = 5
AND `Entry`.`read` = 1
GROUP BY `Entry`.`feed_id`   

这会导致以下错误:

SQL Error: 1054: Unknown column 'Entry.feed_id' in 'field list' [CORE/cake/libs/model/datasources/dbo_source.php, line 684]

我看到了 SQL 的问题,可以手写一个查询来做我想做的事,但这似乎是在 CakePHP 中应该可以做的事情,而无需求助于手工制作的 SQL。

我应该如何设置我的find() 调用来做我想做的事,从 MVC 的角度来看,我通过 FeedsController 查找未读条目的计划是否有意义?

【问题讨论】:

    标签: sql cakephp join model find


    【解决方案1】:

    您可以在 Feeds 控制器中使用它。

    /**
     * Bind the Feed model to the Entry model
     * and set a condition of 'read' => false
     */
    $this->Feed->bindModel(array(
      'hasMany' => array(
        'Entry' => array(
          'conditions' => array(
            'Entry.read' => false
          )
        )
      )
    ));
    
    /**
     * Get all the feeds and their accompanying
     * entries that belong to the current user
     */
    $unread = $this->Feed->find('all', array(
      'conditions' => array(
        'Feedfolder.user_id' => $this->Auth->user('id')
      )
    ));
    

    这里发生了什么?

    首先,我们使用 hasManyFeed 模型与 Entry 模型绑定。同时,我们还设置了一个条件('Entry.read' => false),保证只返回未读消息。

    其次,我们可以在 Feed 模型上调用 find,设置 Feedfolder 应该属于当前用户的条件。

    【讨论】:

    • 这是我需要的 90% 的方法,我错了我真正想要的东西。我需要获取按提要 ID 分组的未读条目数。这段代码可以适应吗?
    • @theraccoonbear - 查看我的新答案。这有点啰嗦,但它确实完成了工作。希望对你有效。莫兹
    【解决方案2】:

    让我们再试一次。这一次,我直接从 Entries 控制器工作。

    /**
     * Unbind the existing relationship with Feed
     */
    $this->Entry->unbindModel(array(
      'belongsTo' => array('Feed')
    ));
    
    /**
     * Explicitly bind of the 'parent' models
     */
    $this->Entry->bindModel(array(
      'hasOne' => array(
        'Feed' => array(
          'foreignKey' => false,
          'conditions' => array('Feed.id = Entry.feed_id')
        ),
        'Feedfolder' => array(
          'foreignKey' => false,
          'conditions' => array('Feedfolder.id = Feed.feedfolder_id')
        ),
        'User' => array(
          'foreignKey' => false,
          'conditions' => array('User.id = Feedfolder.user_id')
        )
      )
    ));
    
    /**
     * Find the entries that are unread and belong to the current user
     * and then Group by Feed.id
     */
    $unread = $this->Entry->find('all', array(
      'fields' => array(
        'Feed.Title',
        'COUNT(Entry.id) AS UnreadCount'
      ),
      'conditions' => array(
        'Entry.read' => 0,
        'User.id' => $this->Auth->user('id')
      ),
      'group' => array(
        'Feed.id'
      )
    ));
    

    这里发生了什么?

    首先,我们解除Feed模型的绑定。

    其次,我们将 Entry 模型与 FeedFeedfolderUser 模型显式绑定。这可以防止 Cake 尝试使用它的自动魔力(顺便说一句,这仍然很棒)。

    最后,我们在 Entry 模型上调用 find 并设置我们需要的条件:未读的条目属于当前用户。然后,我们按 Feed.id 对其进行分组。

    【讨论】:

      【解决方案3】:

      试试这个

      $this->Category->bindModel(
                  array('belongsTo' => array(
                          'ParentCategory' => array('className' => 'Category',
      
       'foreignKey' => 'parent_id'),
          )));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        • 2012-07-20
        • 1970-01-01
        相关资源
        最近更新 更多