Custom match in association definition?
I have two models: contacts and groups with a belongsToMany association.
I only want to get groups that are available for contact. For this I have a custom search.
public function findAccessible(Query $query, array $options){
return $query
->where(['admin_user_id' => $options['User.id']])
->orWhere(['public' => true])
->matching('Users', function($q) use ($options){
return $q->orWhere(['Users.id' => $options['User.id']]);
});
}
So I can call the next one and I get what I want.
$accessibleGroups = $this->Contacts->Groups->find('accessible', ['User.id' => $this->Auth->user('id')]);
But if I have a containment element it will return all groups, not just the ones available.
$contact = $this->Contacts->get($id, [
'contain' => ['Groups']
]);
How to restrict access available?
I cannot add a custom finder to the definition property of the table's association definition as I cannot pass $ options there. Or can I?
source to share
Let me quote the docs and tests (if you can't find something in the docs, tests are often a useful source of information on how to do things).
http://book.cakephp.org/3.0/en/orm/table-objects.html#passing-conditions-to-contain
If you have defined some custom lookup methods in your linked table, you can use them internally:
// Bring all articles, but only bring the comments that are approved and // popular. $query = $articles->find()->contain([ 'Comments' => function ($q) { return $q->find('approved')->find('popular'); } ]);
In this scenario, you can simply pass the conditions in the call find()
just like you did.
http://book.cakephp.org/3.0/en/orm/table-objects.html#using-the-finder-option
So, there is also this "hidden" finder
parameter, which can be used instead of the called one:
$table->find('all')
->where(['Articles.author_id' => $authorId])
->contain([
'Authors' => [
'finder' => ['byAuthor' => ['author_id' => $authorId]]
]
]);
I guess it won't hurt if the use of the finder is documented in a little more detail in the Cookbook, the docblock for Query::contain()
also lacks information on this.
source to share