如何在CakePhp索引中添加相关记录的计数

时间:2015-01-26 12:23:38

标签: php mysql cakephp

我正在申请为青年团体存储记录。

这个青年团体有一个成员徽章系统,我有以下表格;

成员 徽章 member_badges

前两个表格是自我解释的,成员是青年组成员,徽章是徽章的名称,例如。 FieldCraft,救生,急救等。

member_badges记录成员的成就,并具有member_id,badge_id,尝试日期和状态(通过或失败)。我们记录失败的尝试,因为它将帮助我们衡量课程的有效性 - 通过率等等。

我想创建一个包含以下数据的表格;

徽章|尝试次数|通过|失败

我已经创建了一个badgeController函数,如下所示;

public function badgereportsummary() {

    $paginate = array(
        'contain' => array('MemberBadge'));

    $this->Paginator->settings = $paginate;
    $this->set('badges', $this->paginate());
}

现在它以一种方式工作 - 它返回一个徽章数组,每个徽章都包含一个成员徽章数组,并且我已经在视图中使用以下内容进行了粗略的准备页面工作

echo h(count($badge['MemberBadge']));

但是 - 这不允许我对此字段进行排序,并且在将来我还希望添加限制日期范围的功能,例如"显示从2015年1月1日到30/3/15"尝试的急救徽章计数。我在网上看到了一些关于使用counterCache的建议(我已经在应用程序的其他地方使用过了)但是这不允许我计算日期范围内的计数等。

我想我想要的是将特定页面上的成员徽章的数量添加为控制器中的虚拟字段。我一直在搜索文档和谷歌,并且整天在键盘上敲打我的脑袋而无法解决问题。任何关于如何完成这一点的建议都非常感谢。

1 个答案:

答案 0 :(得分:0)

您的摘要报告(徽章 | 尝试次数 | 传递 | 失败)看起来需要SQL语句如:

SELECT badge.description AS Badge
  , COUNT(*) AS NumberOfAttempts
  , SUM(IF(member_badges.status = 'Fail',0,1)) AS Fails 
  , SUM(IF(member_badges.status = 'Pass',0,1)) AS Passes 
FROM member_badges
JOIN badges ON badges.id = member_badges.badge_id
WHERE member_badges.date_of_attempt BETWEEN '20140101' AND '20140131'
GROUP BY badge.description
ORDER BY NumberOfAttempts DESC;

然后我会更改 badgereportsummary 方法来生成此SQL,这相对简单。

  1. 将功能从徽章控制器模型移至MemberBadge模型
  2. 为方法中的新列名创建虚拟字段 - >
    1. $this->MemberBadge->virtualFields['NumberOfAttempts'] = 0;
    2. $this->MemberBadge->virtualFields['Fails'] = 0;
    3. $this->MemberBadge->virtualFields['Passes'] = 0;
  3. 写下发现:
  4. 代码示例

    $fields = array('Badge.description'
                    ,'COUNT(*) AS MemberBadge__NumberOfAttempts'
                    ,'SUM(IF(MemberBadge.status = 'Fail',0,1)) AS MemberBadge__Fails' 
                    ,'SUM(IF(MemberBadge.status = 'Pass',0,1)) AS MemberBadge__Passes');
    return $this->find('all'
           ,'conditions' => array('MemberBadge.date_of_attempt BETWEEN ? AND ?' => array($start_date,$end_date)
           ,'fields' => $fields
           ,'order' => array('NumberOfAttempts DESC')
           ,'group' => array('Badge.description'));
    

    然后在任何徽章控制器方法中调用$this->Badge->MemberBadge-> badgereportsummary($start_date, $end_date)

    我不会使用永久虚拟字段(即,在模型中定义虚拟字段),因为这是一个聚合函数。此外,我不会因为您的确切原因而使用counterCache - 需要根据其他字段过滤结果。