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

这个青年组有一个徽章系统供会员使用,我有下表。

成员
徽章
会员徽章

前两个表不言自明,成员是青年组成员,徽章是徽章的名称,例如。 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());
}


现在,它以一种时尚的方式工作-它返回一个Badge数组,每个Badge包含一个Member Badge数组,我在View中有一个粗略的页面准备工作,其中包含以下内容

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


但是-这将不允许我在此字段上进行排序,并且将来我想添加限制日期范围的功能,例如“告诉我从1/1/15到30/3/15尝试的急救徽章的数量”。我在网上看到了一些有关使用counterCache的建议(我已经在应用程序的其他位置使用了该建议),但是这不允许我计算出日期范围等的计数。

我想我要添加的是在特定页面上的会员徽章计数作为控制器中的虚拟字段。我一直在搜索文档和Google,并整日在键盘上敲打着头,无法解决。任何有关如何实现这一目标的建议,将不胜感激。

最佳答案

您的摘要报告(“标志|尝试次数|通过|失败”)看起来像需要以下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,这相对简单。


将功能从徽章控制器模型移动到MemberBadge模型
在方法->中为新列名创建虚拟字段

$this->MemberBadge->virtualFields['NumberOfAttempts'] = 0;
$this->MemberBadge->virtualFields['Fails'] = 0;
$this->MemberBadge->virtualFields['Passes'] = 0;

写发现:


代码示例

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

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

09-16 13:35