ユーザーと連絡先にbelongsToManyアソシエーションがあります。
指定されたユーザーの連絡先を検索したいのですが。私は次のようなものが必要になります
$this->Contacts->find()->contain(['Users' => ['Users.id' => 1]]);
クックブックには、含める条件の指定、カスタムFinderメソッド、および関連付けキーによる歌唱について説明されていますが、これらを組み合わせる方法がわかりませんでした。
Contacts
テーブルからクエリを実行する場合、探しているのはQuery::matching()
またはQuery::innerJoinWith()
であり、Query::contain()
だけではありません。
クックブック>データベースアクセスとORM>クエリビルダー>関連データによるフィルタリング を参照してください。
テーブルを使用した例を次に示します。
_$this->Contacts
->find()
->matching('Users', function(\Cake\ORM\Query $q) {
return $q->where(['Users.id' => 1]);
});
_
これにより、生成されたクエリに必要な結合+条件が自動的に追加されるため、IDが_1
_の少なくとも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]);
});
_
これには、連絡先に属するすべてのユーザーが含まれます。
複数の一致があり、それらの一致のみを含めたい場合は、包含もフィルタリングする必要があります。この例では、一致するものが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');
_
重複する可能性がある場合、つまり1つの連絡先に複数のアクティブユーザーがいる可能性がある場合は、重複する連絡先レコードを取得しないように、それに応じてグループ化することをお勧めします。
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
プロパティで見つけることができます。
@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に設定されているユーザーとの連絡先が表示されました。それとも私は複雑すぎて、より良い解決策がありますか?