如何根据相关模型的条件进行过滤?
我有一个用户和联系人belongsToMany关联。
我想find给定用户的联系人。 我需要类似的东西
$this->Contacts->find()->contain(['Users' => ['Users.id' => 1]]);
这本食谱讲的是赋予条件包含自定义的发现方法和通过关键字唱歌,但我没有find如何把它们放在一起。
使用Query :: matching()或Query :: innerJoinWith()
当从Contacts
表中查询时,你要查找的是Query::matching()
或Query::innerJoinWith()
,而不是(仅) Query::contain()
Query::innerJoinWith()
Query::contain()
。
请参阅Cookbook>数据库访问和ORM>查询生成器>按关联数据进行筛选
以下是使用表格的示例:
$this->Contacts ->find() ->matching('Users', function(\Cake\ORM\Query $q) { return $q->where(['Users.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]); });
深度关联
您还可以通过使用从Query::contain()
Users hasOne Xyz
Query::contain()
已知的点注释path语法来定位更深的关联,例如,如果您还有一个Users hasOne Xyz
关联,则可以使用Xyz.id
进行过滤
->matching('Users.Xyz', function(\Cake\ORM\Query $q) { return $q->where(['Xyz.id' => 1]); })
改为从其他表中select
有了这些关联和简单的需求,你也可以很容易地从另一端查询,即通过Users
表,并使用Query::contain()
来包含关联的联系人,如
$this->Users ->find() ->contain('Contacts') ->where([ 'Users.id' => 1 ]) ->first();
所有联系人都可以在实体contacts
属性中find。