我在用户和通讯录上有一个belongsToMany关联。
我想找到给定用户的联系人。 我需要像
这样的东西$this->Contacts->find()->contain(['Users' => ['Users.id' => 1]]);
这本食谱讲的是提供包含条件,自定义查找器方法和通过关联键唱歌,但我没有找到如何将它们放在一起。
答案 0 :(得分:20)
从Contacts
表格查询时,您要找的是Query::matching()
或Query::innerJoinWith()
,而不是{仅} Query::contain()
。
请参阅Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data
以下是使用您的表格的示例:
$this->Contacts
->find()
->matching('Users', function(\Cake\ORM\Query $q) {
return $q->where(['Users.id' => 1]);
});
这将自动将所需的连接+条件添加到生成的查询中,以便仅检索与至少一个ID为1
的用户关联的联系人。
如果您通过hasMany
和belongsTo
手动设置多对多关联,则可以直接定位联接表:
$this->Contacts
->find()
->matching('ContactsUsers', function(\Cake\ORM\Query $q) {
return $q->where(['ContactsUsers.user_id' => 1]);
});
如果您确实想要在结果中返回所有关联,那么继续使用contain()
:
$this->Contacts
->find()
->contain('Users')
->matching('Users', function(\Cake\ORM\Query $q) {
return $q->where(['Users.id' => 1]);
});
这将包含属于联系人的所有用户。
如果您有多个匹配项,并且您只想包含这些匹配项,那么您也必须过滤包含这些匹配项。在这个例子中它没有多大意义,因为只有一个匹配,但在其他情况下它可能是有用的,例如,如果你想匹配所有拥有活动用户的联系人,并检索联系人仅包括活动的关联用户:
$this->Contacts
->find()
->contain(['Users' => function(\Cake\ORM\Query $q) {
return $q->where(['Users.active' => true]);
}])
->matching('Users', function(\Cake\ORM\Query $q) {
return $q->where(['Users.active' => true]);
})
->group('Contacts.id');
鉴于可能存在重复项,即单个联系人的多个活跃用户,您可能希望相应地对事物进行分组,以避免检索重复的联系人记录。
通过使用Query::contain()
中已知的点标记路径语法,您还可以通过这种方式定位更深层次的关联。例如,您有一个Users hasOne Profiles
关联,并且您希望仅匹配那些想要接收通知的用户,这可能看起来像这样:
->matching('Users.Profiles', function(\Cake\ORM\Query $q) {
return $q->where(['Profiles.receive_notifications' => true]);
})
这将自动创建所有必需的附加连接。
通过这些关联和您的简单要求,您还可以从另一方轻松查询,即通过Users
表并仅使用Query::contain()
来包含相关联系人,例如
$this->Users
->find()
->contain('Contacts')
->where([
'Users.id' => 1
])
->first();
然后可以在实体contacts
属性中找到所有联系人。
答案 1 :(得分:0)
虽然@ndm的答案使我遇到了类似的问题,但解决方案仍需要一些调整。 问题是让用户被joinTable上的数据过滤,添加匹配项不会返回用户。因此,这就是我最终希望得到的帮助。
$this->Contacts
->find()
->contain('Users', function(\Cake\ORM\Query $q) {
return $q->matching('ContactsUsers', function(\Cake\ORM\Query $q) {
return $q->where(['ContactsUsers.some_field' => 1]);
}
});
这使我与关联表中some_field设置为1的用户联系。还是我过于复杂,有更好的解决方案?