Skip to content

Commit

Permalink
Adding Query::matching as an easier way to add filtered containments
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Jan 5, 2014
1 parent 679b832 commit 714ae00
Showing 1 changed file with 55 additions and 9 deletions.
64 changes: 55 additions & 9 deletions Cake/ORM/Query.php
Expand Up @@ -239,15 +239,6 @@ public function addDefaultTypes(Table $table) {
* ]
* ]);
*
* // Bring only articles that were tagged with 'cake'
* $query->contain([
* 'Tag' => [
* 'matching' => true,
* 'conditions' => ['Tag.name' => 'cake']
* ]
* ]);
* }}}
*
* If called with no arguments, this function will return an ArrayObject with
* with the list of previously configured associations to be contained in the
* result. This object can be modified directly as the reference is kept inside
Expand Down Expand Up @@ -306,6 +297,61 @@ public function contain($associations = null, $override = false) {
return $this;
}

/**
* Adds filtering conditions to this query to only bring rows that have a relation
* to another from an associated table, based on conditions in the associated table.
*
* This function will add entries in the ``contain`` graph.
*
* ### Example:
*
* {{{
* // Bring only articles that were tagged with 'cake'
* $query->matching('Tags', function($q) {
* return $q->where(['name' => 'cake']);
* );
* }}}
*
* It is possible to filter by deep associations by using dot notation:
*
* ### Example:
*
* {{{
* // Bring only articles that were commented by 'markstory'
* $query->matching('Comments.Users', function($q) {
* return $q->where(['username' => 'markstory']);
* );
* }}}
*
* As this function will create ``INNER JOIN``, you might want to consider
* calling ``distinct`` on this query as you might get duplicate rows if
* your conditions don't filter them already. This might be the case, for example,
* of the same user commenting more than once in the same article.
*
* ### Example:
*
* {{{
* // Bring unique articles that were commented by 'markstory'
* $query->distinct(['Articles.id'])
* ->matching('Comments.Users', function($q) {
* return $q->where(['username' => 'markstory']);
* );
* }}}
*
* Please note that the query passed to the closure will only accept calling
* ``select``, ``where``, ``andWhere`` and ``orWhere`` on it. If you wish to
* add more complex clauses you can do it directly in the main query.
*
* @param string $assoc The association to filter by
* @param callable $builder a function that will receive a pre-made query object
* that can be used to add custom conditions or selecting some fields
* @return Query
*/
public function matching($assoc, callable $builder = null) {
$options = ['queryBuilder' => $builder, 'matching' => true];
return $this->contain([$assoc => array_filter($options)]);
}

/**
* Formats the containments array so that associations are always set as keys
* in the array. This function merges the original associations array with
Expand Down

0 comments on commit 714ae00

Please sign in to comment.