Skip to content
Permalink
Browse files

Fix case where an association find() is then eagerloaded on.

When an association find() then has the reverse side eagerloaded, the
joins would be incorrectly ordered. Before attaching the eagerloader, we
need to remove the old join to ensure the new join is put at the end.

Refs #7707
  • Loading branch information...
markstory committed Dec 6, 2015
1 parent f25eac3 commit 5f4798a1d922e82ac6dd385914bbf68f4240c6a7
Showing with 44 additions and 4 deletions.
  1. +23 −4 src/ORM/Association/BelongsToMany.php
  2. +21 −0 tests/TestCase/ORM/QueryRegressionTest.php
@@ -320,11 +320,13 @@ public function attachTo(Query $query, array $options = [])
$includeFields = $options['includeFields'];
}
$assoc = $this->_targetTable->association($junction->alias());
$query->removeJoin($assoc->name());
unset($options['queryBuilder']);
$type = array_intersect_key($options, ['joinType' => 1, 'fields' => 1]);
$options = ['conditions' => [$cond]] + compact('includeFields');
$options['foreignKey'] = $this->targetForeignKey();
$assoc = $this->_targetTable->association($junction->alias());
$assoc->attachTo($query, $options + $type);
$query->eagerLoader()->addToJoinsMap($junction->alias(), $assoc, true);
}
@@ -788,9 +790,25 @@ function () use ($sourceEntity, $targetEntities, $options) {
public function find($type = null, array $options = [])
{
$query = parent::find($type, $options);
if ($this->conditions()) {
$query->contain([$this->junction()->alias()]);
if (!$this->conditions()) {
return $query;
}
$junction = $this->junction();
$target = $this->target();
$belongsTo = $junction->association($target->alias());
$conditions = $belongsTo->_joinCondition([
'foreignKey' => $this->foreignKey()]
);
$join = [
'table' => $junction->table(),
'conditions' => $conditions,
'type' => 'INNER'
];
$name = $this->_junctionAssociationName();
$query->join([$name => $join]);
$query->eagerLoader()->addToJoinsMap($name, $belongsTo);
return $query;
}
@@ -1062,7 +1080,8 @@ protected function _buildQuery($options)
{
$name = $this->_junctionAssociationName();
$query = $this->_buildBaseQuery($options);
$joins = $query->join() ?: [];
$joins = $query->join();
$keys = $this->_linkField($options);
$matching = [
@@ -120,6 +120,27 @@ public function testBelongsToManyAssociationProxyFindWithConditions()
$this->assertCount(1, $result);
}
/**
* Test that association proxy find() with matching resolves joins correctly
*
* @return void
*/
public function testBelongsToManyAssociationProxyFindWithConditionsMatching()
{
$table = TableRegistry::get('Articles');
$table->belongsToMany('Tags', [
'foreignKey' => 'article_id',
'associationForeignKey' => 'tag_id',
'conditions' => ['SpecialTags.highlighted' => true],
'through' => 'SpecialTags'
]);
$query = $table->Tags->find()->matching('Articles', function ($query) {
return $query->where(['Articles.id' => 1]);
});
// The inner join on special_tags excludes the results.
$this->assertEquals(0, $query->count());
}
/**
* Tests that duplicate aliases in contain() can be used, even when they would
* naturally be attached to the query instead of eagerly loaded. What should

0 comments on commit 5f4798a

Please sign in to comment.
You can’t perform that action at this time.