Cakephp 如何按条件筛选关联模型?
我有一个关于用户和联系人的私人协会 我想找到给定用户的联系人。 我需要像这样的东西Cakephp 如何按条件筛选关联模型?,cakephp,associations,conditional-statements,cakephp-3.0,query-builder,Cakephp,Associations,Conditional Statements,Cakephp 3.0,Query Builder,我有一个关于用户和联系人的私人协会 我想找到给定用户的联系人。 我需要像这样的东西 $this->Contacts->find()->contain(['Users' => ['Users.id' => 1]]); 这本食谱谈到了提供包含条件、自定义查找器方法和通过关联键进行搜索,但我没有找到如何将它们组合在一起。使用Query::matching()或Query::innerJoinWith() 当从联系人表查询时,您要查找的是Query::matching()
$this->Contacts->find()->contain(['Users' => ['Users.id' => 1]]);
这本食谱谈到了提供包含条件、自定义查找器方法和通过关联键进行搜索,但我没有找到如何将它们组合在一起。使用Query::matching()或Query::innerJoinWith()
当从联系人
表查询时,您要查找的是Query::matching()
或Query::innerJoinWith()
,而不是(仅)Query::contain()
请注意,innerJoinWith()
通常是首选,以避免出现严格分组问题,因为matching()
会将关联字段添加到选择列表中,这可能会导致问题,因为它们通常不依赖于功能
看
下面是一个使用表格的示例:
$this->Contacts
->find()
->innerJoinWith('Users', function(\Cake\ORM\Query $q) {
return $q->where(['Users.id' => 1]);
});
这将自动将所需的连接+条件添加到生成的查询中,以便仅检索与至少一个id为1
的用户关联的联系人
以联接表为目标
如果您需要通过hasMany
和belongsTo
手动设置多对多关联,您可以直接针对联接表:
$this->Contacts
->find()
->innerJoinWith('ContactsUsers', function(\Cake\ORM\Query $q) {
return $q->where(['ContactsUsers.user_id' => 1]);
});
包括集装箱
如果您确实希望在结果中返回所有关联,那么也只需继续使用contain()
:
$this->Contacts
->find()
->contain('Users')
->innerJoinWith('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]);
}])
->innerJoinWith('Users', function(\Cake\ORM\Query $q) {
return $q->where(['Users.active' => true]);
})
->group('Contacts.id');
考虑到可能存在重复的联系人,即单个联系人有多个活动用户,您可能希望相应地对内容进行分组,以避免检索重复的联系人记录
深联想
通过使用Query::contain()
中的点符号路径语法,您还可以通过这种方式定位更深层次的关联。例如,假设您有一个用户拥有一个Profiles
关联,并且您只希望匹配那些希望接收通知的用户,这可能类似于:
->innerJoinWith('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();
所有联系人都可以在entities
contacts
属性中找到。虽然@ndm answer解决了我需要解决的类似问题,但解决方案需要稍加调整。
问题是让用户通过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]);
}
});
这使我与关联表中某些_字段设置为1的用户取得了联系。还是我太复杂了,有更好的解决方案?谢谢,不知怎么的,我错过了这一部分。谢谢。昨天我无意中发现了另一种方法来完成更新中包含的内容$此->联系人->查找()->包含(['users'])->匹配('users',函数($q){return$q->where(['users.id'=>1]);});看:@rrd啊,我应该仔细阅读这篇文章,第一眼我就觉得这两篇文章都不会给你想要的结果。现在,有人需要找出套管技巧是否与更“复杂”的附加关联解决方案一样可行:)当条件为
return$q->where(['ContactsUsers.user_id IN'=>[1,2,3]]时,我会得到重复的结果代码>。请让我知道如何获得独特的结果?或者请在这里回答@ndm@SumonSarker选中“链接文档”部分下的警告框,您必须执行或相应地应用(两者都使用主键)。