Browse Source

Merge pull request #10657 from cakephp/issue-10633

Fix invalid SQL on paginated results.
Mark Story 8 years ago
parent
commit
e9f83872a2

+ 14 - 0
src/ORM/EagerLoader.php

@@ -829,4 +829,18 @@ class EagerLoader
 
         return $keys;
     }
+
+    /**
+     * Clone hook implementation
+     *
+     * Clone the _matching eager loader as well.
+     *
+     * @return void
+     */
+    public function __clone()
+    {
+        if ($this->_matching) {
+            $this->_matching = clone $this->_matching;
+        }
+    }
 }

+ 1 - 0
src/ORM/Query.php

@@ -765,6 +765,7 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
         $clone->formatResults(null, true);
         $clone->setSelectTypeMap(new TypeMap());
         $clone->decorateResults(null, true);
+        $clone->setEagerLoader(clone $this->getEagerLoader());
 
         return $clone;
     }

+ 36 - 0
tests/TestCase/ORM/QueryRegressionTest.php

@@ -176,6 +176,42 @@ class QueryRegressionTest extends TestCase
     }
 
     /**
+     * Tests that eagerloading and hydration works for associations that have
+     * different aliases in the association and targetTable
+     *
+     * @return void
+     */
+    public function testEagerLoadingNestedMatchingCalls()
+    {
+        $this->loadFixtures('Articles', 'Authors', 'Tags', 'ArticlesTags', 'AuthorsTags');
+        $articles = TableRegistry::get('Articles');
+        $articles->belongsToMany('Tags', [
+            'foreignKey' => 'article_id',
+            'targetForeignKey' => 'tag_id',
+            'joinTable' => 'articles_tags'
+        ]);
+        $tags = TableRegistry::get('Tags');
+        $tags->belongsToMany('Authors', [
+            'foreignKey' => 'tag_id',
+            'targetForeignKey' => 'author_id',
+            'joinTable' => 'authors_tags'
+        ]);
+
+        $query = $articles->find()
+            ->matching('Tags', function ($q) {
+                return $q->matching('Authors', function ($q) {
+                    return $q->where(['Authors.name' => 'larry']);
+                });
+            });
+        $this->assertEquals(3, $query->count());
+
+        $result = $query->first();
+        $this->assertInstanceOf(EntityInterface::class, $result);
+        $this->assertInstanceOf(EntityInterface::class, $result->_matchingData['Tags']);
+        $this->assertInstanceOf(EntityInterface::class, $result->_matchingData['Authors']);
+    }
+
+    /**
      * 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
      * happen here is that One of the duplicates will be changed to be loaded using

+ 11 - 3
tests/TestCase/ORM/QueryTest.php

@@ -2714,12 +2714,20 @@ class QueryTest extends TestCase
         $query->offset(10)
             ->limit(1)
             ->order(['Articles.id' => 'DESC'])
-            ->contain(['Comments']);
+            ->contain(['Comments'])
+            ->matching('Comments');
         $copy = $query->cleanCopy();
 
         $this->assertNotSame($copy, $query);
-        $this->assertNotSame($copy->eagerLoader(), $query->eagerLoader());
-        $this->assertNotEmpty($copy->eagerLoader()->contain());
+        $copyLoader = $copy->getEagerLoader();
+        $loader = $query->getEagerLoader();
+        $this->assertEquals($copyLoader, $loader, 'should be equal');
+        $this->assertNotSame($copyLoader, $loader, 'should be clones');
+        $this->assertNotSame(
+            $this->readAttribute($copyLoader, '_matching'),
+            $this->readAttribute($loader, '_matching'),
+            'should be clones'
+        );
         $this->assertNull($copy->clause('offset'));
         $this->assertNull($copy->clause('limit'));
         $this->assertNull($copy->clause('order'));