我有一个包含Rounds和Users的数据库。 Rounds属于许多用户和用户所属的ToMany Rounds,因此是多对多的关系。添加了连接表rounds_users来执行此操作。 编辑:在这里使用了错误的短语。我的意思是'belongsToMany'而不是'hasMany'
现在我想检索一个Rounds列表,以及每轮链接用户的数量。
如果是一对多关系,以下内容将起作用:
$rounds = $this->Rounds->find()
->contain(['Users' => function ($q)
{
return $q->select(['Users.id', 'number' => 'COUNT(Users.round_id)'])
->group(['Users.round_id']);
}
]);
......根据Count in contain Cakephp 3
但是,在多对多关系中Users.round_id
不存在。那么,有什么可以改变呢?
注意:已经提出了几个这样的问题,但很少有关于CakePHP 3.x的问题,所以我仍然想尝试一下。
注2:我可以通过使用PHP函数count
解决这个问题,但我宁愿更优雅地做到这一点
编辑:如下所示,手动加入似乎可以解决问题:
$rounds_new = $this->Rounds->find()
->select($this->Rounds)
->select(['user_count' => 'COUNT(Rounds.id)'])
->leftJoinWith('Users')
->group('Rounds.id');
......有一个问题!没有用户的轮次仍然会得到user_count
等于1.可能是什么问题?
答案 0 :(得分:1)
正如评论中已经提到的,您可以随时加入关联而不是包含它们(有点像SUM() on ManyToMany question)。
您为没有任何关联用户的回合检索1
计数的原因是您指望错误的表。点数Rounds
当然会产生至少1
的计数,因为总会有至少1
轮,没有关联用户的回合。
如此长的故事,请指望Users
:
$rounds = $this->Rounds
->find()
->select($this->Rounds)
->select(function (\Cake\ORM\Query $query) {
return [
'user_count' => $query->func()->count('Users.id')
];
})
->leftJoinWith('Users')
->group('Rounds.id');
belongsToMany
关联的计数器缓存还有计数器缓存行为,它也适用于belongsToMany
关联,只要它们设置为使用具体的连接表类,可以通过关联配置through
选项进行配置:
class RoundsTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Users', [
'through' => 'RoundsUsers'
]);
}
}
class UsersTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Rounds', [
'through' => 'RoundsUsers'
]);
}
}
计数器缓存将在连接表类中设置,在此示例RoundsUsersTable
中,它将有两个belongsTo
个关联,一个到Rounds
,一个到{{1} }:
Users
如果您实际上已经明确创建了class RoundsUsersTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Rounds');
$this->belongsTo('Users');
$this->addBehavior('CounterCache', [
'Rounds' => ['user_count']
]);
}
}
个关联(而不是belongsToMany),那么您将拥有hasMany
关系,即您仍然可以使用链接的“ count in contain “示例来自one Rounds to many RoundsUsers
。
然而,这将使您得到一个结构,其中计数将被放置在嵌套实体中,而对于没有任何关联用户的轮次,这又会丢失。我想在大多数情况下这种结构需要重新格式化,所以它可能不是最好的解决方案。但是,为了完成,这是一个例子:
RoundsUsers