I have a belongsToMany association on Users and Contacts.
I would like to find the Contacts of the given User. I would need something like
$this->Contacts->find()->contain(['Users' => ['Users.id' => 1]]);
The cookbook speaks about giving conditions to contain, custom finder methods and sing through association key, but I did not find out how to put these together.
Use Query::matching() or Query::innerJoinWith()
When querying from the
Contacts
table, then what you are looking for isQuery::matching()
orQuery::innerJoinWith()
, not (only)Query::contain()
.See Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data
Here's an example using your tables:
This will automatically add the required joins + conditions to the generated query, so that only those contacts are being retrieved that are associated to at least one user with the id
1
.Target the join table
In case you'd have a manually set up many to many association via
hasMany
andbelongsTo
, you can directly target the join table:Including containments
In case you actually want to have all the associations returned in your results too, then just keep using
contain()
too:That would contain all users that belong to a contact.
Restricting containments
In cases where you have multiple matches, and you'd wanted to contain only those matches, you'd have to filter the containment too. In this example it doesn't make much sense since there would be only one match, but in other situations it might be useful, say for example if you'd wanted to match all contacts that have active users, and retrieve the contacts including only the active associated users:
Given that there could be duplicates, ie multiple active users for a single contact, you'll probably want to group things accordingly, in order to avoid retrieving duplicate contact records.
Deep associations
You can also target deeper associations that way, by using the dot notated path syntax known from
Query::contain()
. Say for example you had aUsers hasOne Profiles
association, and you want to match only on those users that want to receive notifications, that could look something like this:This will automatically create all the required additional joins.
Select from the other table instead
With these associations and your simple requirements, you could also easily query from the other side, ie via the
Users
table and use justQuery::contain()
to include the associated contacts, likeAll the contacts can then be found in the entities
contacts
property.