Skip to content

Commit

Permalink
Implemented notMatching for belongsToMany tables
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Jun 6, 2015
1 parent 2d35e45 commit cd4cc09
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 10 deletions.
21 changes: 13 additions & 8 deletions src/ORM/Association.php
Expand Up @@ -499,14 +499,6 @@ public function attachTo(Query $query, array $options = [])
}
}

if ($options['negateMatch']) {
$primaryKey = $query->aliasFields((array)$target->primaryKey(), $this->_name);
$query->andWhere(function ($exp) use ($primaryKey) {
array_map([$exp, 'isNull'], $primaryKey);
return $exp;
});
}

list($finder, $opts) = $this->_extractFinder($options['finder']);
$dummy = $this
->find($finder, $opts)
Expand All @@ -531,6 +523,19 @@ public function attachTo(Query $query, array $options = [])
$this->_appendFields($query, $dummy, $options);
$this->_formatAssociationResults($query, $dummy, $options);
$this->_bindNewAssociations($query, $dummy, $options);
$this->_appendNotMatching($query, $options);
}

protected function _appendNotMatching($query, $options)
{
$target = $this->_targetTable;
if (!empty($options['negateMatch'])) {
$primaryKey = $query->aliasFields((array)$target->primaryKey(), $this->_name);
$query->andWhere(function ($exp) use ($primaryKey) {
array_map([$exp, 'isNull'], $primaryKey);
return $exp;
});
}
}

/**
Expand Down
12 changes: 12 additions & 0 deletions src/ORM/Association/BelongsToMany.php
Expand Up @@ -262,6 +262,18 @@ public function attachTo(Query $query, array $options = [])
$query->eagerLoader()->addToJoinsMap($junction->alias(), $assoc, true);
}

protected function _appendNotMatching($query, $options)
{
$target = $junction = $this->junction();
if (!empty($options['negateMatch'])) {
$primaryKey = $query->aliasFields((array)$target->primaryKey(), $target->alias());
$query->andWhere(function ($exp) use ($primaryKey) {
array_map([$exp, 'isNull'], $primaryKey);
return $exp;
});
}
}

/**
* {@inheritDoc}
*/
Expand Down
4 changes: 3 additions & 1 deletion src/ORM/EagerLoader.php
Expand Up @@ -191,9 +191,11 @@ public function matching($assoc = null, callable $builder = null, $options = [])
$containments = [];
$pointer =& $containments;
$options += ['joinType' => 'INNER'];
$opts = ['matching' => true] + $options;
unset($opts['negateMatch']);

foreach ($assocs as $name) {
$pointer[$name] = ['matching' => true] + $options;
$pointer[$name] = $opts;
$pointer =& $pointer[$name];
}

Expand Down
33 changes: 32 additions & 1 deletion tests/TestCase/ORM/QueryTest.php
Expand Up @@ -2848,7 +2848,7 @@ public function testInnerJoinWithSelect()
public function testNotMatching()
{
$table = TableRegistry::get('authors');
$articles = $table->hasMany('articles');
$table->hasMany('articles');

$results = $table->find()
->hydrate(false)
Expand All @@ -2874,4 +2874,35 @@ public function testNotMatching()
];
$this->assertEquals($expected, $results);
}

public function testNotMatchingBelongsToMany()
{
$table = TableRegistry::get('articles');
$table->belongsToMany('tags');

$results = $table->find()
->hydrate(false)
->notMatching('tags', function ($q) {
return $q->where(['tags.name' => 'tag2']);
})
->toArray();

$expected = [
[
'id' => 2,
'author_id' => 3,
'title' => 'Second Article',
'body' => 'Second Article Body',
'published' => 'Y'
],
[
'id' => 3,
'author_id' => 1,
'title' => 'Third Article',
'body' => 'Third Article Body',
'published' => 'Y'
]
];
$this->assertEquals($expected, $results);
}
}

0 comments on commit cd4cc09

Please sign in to comment.