CakePHP 3如何在Users表中统计深层关联的videos记录数?
在CakePHP 3中实现用户关联视频的深层计数查询
嘿,这个需求我之前做CakePHP项目的时候正好碰到过,要实现这种跨两层关联(users→campaigns→videos)的计数,有两种挺实用的方法,我给你拆解下:
方法一:直接用查询构建器手动关联统计
如果只是临时查询一次,直接用查询构建器做关联统计最直接。我们可以通过leftJoinWith逐层关联到视频表,然后分组统计每个用户的视频总数:
// 在UsersTable或者控制器中编写查询 $users = $this->Users->find() ->select([ // 指定要统计的字段 'post_videos_count' => $this->Users->query()->func()->count('Videos.id') ]) ->leftJoinWith('Campaigns.Videos') // 逐层关联活动和视频表 ->group(['Users.id']) // 按用户ID分组,确保每个用户只返回一条记录 ->enableAutoFields(true); // 自动获取Users表的email、name等字段
说明:
leftJoinWith会创建左连接,即使用户没有任何活动或视频,也会被包含在结果中,此时post_videos_count会显示为0。enableAutoFields(true)可以帮我们自动获取Users表的所有字段(比如email、name),不用手动把每个字段都写在select里。- 最终返回的每个User对象就会包含你想要的
email、name和post_videos_count字段。
方法二:用CounterCache自动维护计数(推荐长期使用)
如果这个计数需要频繁查询,或者希望数据实时自动更新,那用CakePHP的CounterCache行为会更优雅。不过因为是两层关联,我们需要自定义回调来统计总数:
步骤1:先在Users表添加字段
首先给users表新增一个整数类型的字段post_videos_count,默认值设为0。
步骤2:在VideosTable中配置CounterCache
在src/Model/Table/VideosTable.php的initialize方法里添加如下配置:
public function initialize(array $config) { parent::initialize($config); $this->addBehavior('CounterCache', [ 'Users' => [ 'post_videos_count' => function ($event, $entity) { // 获取当前视频所属的活动对应的用户ID $campaign = $this->Campaigns->get($entity->campaign_id); // 统计该用户所有关联的视频总数 return $this->find() ->innerJoinWith('Campaigns') ->where(['Campaigns.user_id' => $campaign->user_id]) ->count(); } ] ]); }
说明:
- 每次新增、删除或修改视频时,这个回调会自动触发,重新计算对应用户的视频总数并更新
post_videos_count字段。 - 之后查询用户的时候,直接读取
post_videos_count字段即可,不需要每次都做关联统计,性能更好。
不管用哪种方法,最终你都会得到符合预期的结果:
User object => [ 'email' => 'email@example.com', 'name' => 'My Name', 'post_videos_count' => 10 ] User object => [ 'email' => 'email2@example.com', 'name' => 'User 2', 'post_videos_count' => 50 ]
内容的提问来源于stack exchange,提问作者Anuj TBE
相关产品推荐
相关产品推荐

