【问题标题】:How do I add a count of related records in CakePhp index如何在 CakePhp 索引中添加相关记录的计数
【发布时间】:2015-01-29 08:42:09
【问题描述】:

我正在开发一个应用程序来存储一个青年团体的记录。

这个青年组有一个徽章系统供成员实现,我有以下表格;

成员 徽章 会员徽章

前两个表是不言自明的,members 是青年组成员, 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 日到 2015 年 3 月 30 日尝试的急救徽章的数量”。我在网上看到了一些关于使用 counterCache 的建议(我在应用程序的其他地方使用过),但这不允许我计算日期范围等的计数。

我想我想要的是将特定页面上的会员徽章计数添加为控制器中的虚拟字段。我一直在搜索文档和谷歌,整天敲打着键盘,无法解决。非常感谢任何有关如何完成此任务的建议。

【问题讨论】:

  • 你应该总是提到你正在使用的确切的 cakephp 版本。
  • 抱歉 - 以为我添加了标签。 CakePHP 2.5.2 和 MySQL 数据库

标签: php mysql cakephp


【解决方案1】:

您的摘要报告(徽章 | 尝试次数 | 通过 | 失败)看起来需要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. 将函数从 Badge 控制器模型移至 MemberBadge 模型
  2. 为方法中的新列名创建虚拟字段 ->
    1. $this->MemberBadge->virtualFields['NumberOfAttempts'] = 0;
    2. $this->MemberBadge->virtualFields['Fails'] = 0;
    3. $this->MemberBadge->virtualFields['Passes'] = 0;
  3. 写下发现:

代码示例

$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'));

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

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

【讨论】:

  • 谢谢 - 这真是一种享受!我的错误在于它基于徽章控制器——我真的需要 MemberBadges。感谢您的建议
猜你喜欢
  • 1970-01-01
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多