CakePHP 3.4+如何按关联状态统计关联记录数量?
解决CakePHP 3.4+中关联数据的状态统计问题
嘿,我来帮你搞定这个按状态统计关联记录的需求!要展示失败数/待处理数/完成数的格式,我们可以直接在查询阶段用聚合函数计算出这三个统计值,比在模板里循环统计高效得多。
方法一:在查询中添加聚合统计字段
我们可以利用SQL的CASE WHEN结合COUNT函数,在find()查询中直接计算每个TableA记录对应的三种状态数量。同时使用leftJoinWith确保即使某条TableA没有对应状态的TableB记录,统计值也会显示为0。
修改后的查询代码如下:
$records = $this->TableA->find() ->select([ // 明确选择TableA需要的字段,或者用enableAutoFields()获取所有字段 'TableA.id', 'TableA.title', // 统计失败状态的数量 'count_failed' => $this->TableA->query()->func()->count( $this->TableA->query()->newExpr()->addCase( ['TableStatus.status' => 'failed'], // 替换成你实际的状态字段名 [1], // 满足条件时返回1 ['integer'] ) ), // 统计待处理状态的数量 'count_pending' => $this->TableA->query()->func()->count( $this->TableA->query()->newExpr()->addCase( ['TableStatus.status' => 'pending'], [1], ['integer'] ) ), // 统计完成状态的数量 'count_complete' => $this->TableA->query()->func()->count( $this->TableA->query()->newExpr()->addCase( ['TableStatus.status' => 'complete'], [1], ['integer'] ) ), ]) ->where([ 'TableA.user_id' => $this->Auth->user('id'), 'TableA.deleted' => false, ]) ->leftJoinWith('TableB.TableStatus') // 左连接确保所有TableA记录都被保留 ->group(['TableA.id']) // 按TableA记录分组聚合 ->enableAutoFields(true); // 如果需要TableA的所有字段,启用这个选项
模板中展示统计结果
现在模板里可以直接使用查询返回的统计字段,不用再手动count()了,记得用h()函数转义内容防止XSS:
<tr> <td>Title</td> <td>Record count</td> </tr> <?php foreach($records as $record): ?> <tr> <td><?= h($record->title) ?></td> <td><?= $record->count_failed ?>/<?= $record->count_pending ?>/<?= $record->count_complete ?></td> </tr> <?php endforeach; ?>
补充说明
- 如果你更习惯用
SUM函数,也可以把count换成sum,逻辑更直观:'count_failed' => $this->TableA->query()->func()->sum( $this->TableA->query()->newExpr()->addCase( ['TableStatus.status' => 'failed'], [1, 0], // 满足返回1,否则返回0 ['integer', 'integer'] ) ), - 请确保代码中的
TableStatus.status是你实际的状态字段名(比如如果字段叫name就改成TableStatus.name)。 - 用
leftJoinWith替代contain是因为我们需要在SQL层面直接聚合关联表的数据,contain更多是用于加载关联实体,不适合这种统计场景。
内容的提问来源于stack exchange,提问作者Anuj TBE
相关产品推荐
相关产品推荐

