1

I'm trying to understand some basic functionality and I'm not sure exactly what topic it falls under. I'm working in CakePHP and I'm trying to understand how these nested callback functions just seem to know what they're supposed to do. I think a lot of my problem is that I don't know what keywords to search so my question is this: how do the anonymous functions in CakePHP associations know a) that the parameter $q is a Query object and b) which model it's supposed to query from?

I can speculate that there's a) somewhere in CakePHP where anonymous functions are told to use the first parameter $q as a query and b) some handler that's traversing the object and assuming that any callback function it finds, no matter how deeply they are nested, is querying the model it's most directly nested under but I can't seem to find any documentation (or what keywords to search for) to understand how and why any of this should work.

Example 1 - this one knows $q is a query and that it's for the AuthorsTable

$query = $articles->find()->contain([
    'Authors' => [
        'foreignKey' => false,
        'queryBuilder' => function ($q) {
            return $q->where(...); // Full conditions for filtering
        }
    ]
]);

Example 2 - This one knows $q is querying the ArticlesTable

$query = $authors->find();
$query->matching('Articles', function ($q) {
    return $q->where(['Articles.created >=' => new DateTime('-10 days')]);
}); 

Thank you in advance... And I apologize if this is a question whose answer can be found on S.O. somewhere else; I'm sure the reason I couldn't find it is because I didn't know what special words to use.

ndm
  • 59,784
  • 9
  • 71
  • 110
Mark W
  • 13
  • 3
  • CakePHP sends you the query object, which is why it knows its a query object – Vindur Dec 22 '17 at 11:48
  • @Vindur I’m not sure how to use what you’re telling me. When you say ‘CakePHP sends you the query object’ that seems vague to me. If I add a parameter like: function($q, $r)... it throws an error about the second parameter. Why? My app knows $q so why does it care that I have a second parameter at all? – Mark W Dec 22 '17 at 21:47

1 Answers1

0

That's just how things work, not only how that specific CakePHP options work, but also how PHP works in general. The function doesn't know anything, all it can do is hoping that the caller (CakePHP, specifically the association class / the association loaders) will invoke it in a way that satisfies its contract.

So you can't define arbitrary contracts, it's CakePHP, ie the caller that dictates the contract that your callbacks must define, as it invokes the callbacks in that specific way, that is that it will pass a query object, which stems from the table associated with the alias that you are passing in the arguments/options (eg Authors = AuthorsTable, Articles = ArticlesTable).

In the shown cases the contract for the callbacks is a signature that looks like

\Cake\Datasource\QueryInterface $query

Your callback must implement a compatible contract, failing to do so will cause an error.

ndm
  • 59,784
  • 9
  • 71
  • 110
  • Ah, okay. So if I want to understand the way CakePHP expects the various callback functions to behave I need to look at that interface file. Perfect, I think that’s exactly what I didn’t understand I needed; QueryInterface. I assume I can figure out the right PHP ‘stuff’ to study from there. Thank you. – Mark W Dec 24 '17 at 07:04
  • @MarkW Well, not really, you need to look at the CakePHP documentation for the specific options/arguments, which should show what the callback signature must look like. – ndm Dec 24 '17 at 13:27