如何根据相关模型的条件进行过滤?

我有一个用户和联系人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]); }); 

这将自动添加所需的连接+条件到生成的查询。

定位连接表

如果您想通过hasManybelongsTo手动设置多对多关联,则可以直接指定连接表:

 $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。