Browse Source

Avoiding forced all fields in a contained belongsToMany, fixes #7913

Jose Lorenzo Rodriguez 10 years ago
parent
commit
c30091537c

+ 13 - 1
src/ORM/Association/BelongsToMany.php

@@ -1095,11 +1095,23 @@ class BelongsToMany extends Association
     protected function _buildQuery($options)
     {
         $name = $this->_junctionAssociationName();
+        $assoc = $this->target()->association($name);
+        $queryBuilder = false;
+
+        if (!empty($options['queryBuilder'])) {
+            $queryBuilder = $options['queryBuilder'];
+            unset($options['queryBuilder']);
+        }
+
         $query = $this->_buildBaseQuery($options);
+        $query->addDefaultTypes($assoc->target());
+
+        if ($queryBuilder) {
+            $query = $queryBuilder($query);
+        }
 
         $keys = $this->_linkField($options);
         $query = $this->_appendJunctionJoin($query, $keys);
-        $assoc = $this->target()->association($name);
 
         $query->autoFields($query->clause('select') === [])
             ->select($query->aliasFields((array)$assoc->foreignKey(), $name));

+ 1 - 10
src/ORM/Association/SelectableAssociationTrait.php

@@ -43,16 +43,7 @@ trait SelectableAssociationTrait
     public function eagerLoader(array $options)
     {
         $options += $this->_defaultOptions();
-        $queryBuilder = false;
-        if (!empty($options['queryBuilder'])) {
-            $queryBuilder = $options['queryBuilder'];
-            unset($options['queryBuilder']);
-        }
-
         $fetchQuery = $this->_buildQuery($options);
-        if ($queryBuilder) {
-            $fetchQuery = $queryBuilder($fetchQuery);
-        }
         $resultMap = $this->_buildResultMap($fetchQuery, $options);
         return $this->_resultInjector($fetchQuery, $resultMap, $options);
     }
@@ -123,7 +114,7 @@ trait SelectableAssociationTrait
         }
 
         if (!empty($options['queryBuilder'])) {
-            $options['queryBuilder']($fetchQuery);
+            $fetchQuery = $options['queryBuilder']($fetchQuery);
         }
 
         return $fetchQuery;

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

@@ -1236,4 +1236,26 @@ class QueryRegressionTest extends TestCase
         // Not executing the query first, just getting the count
         $this->assertEquals(3, $query->count());
     }
+
+    /**
+     * Tests that fetching belongsToMany association will not force
+     * all fields being returned, but intead will honor the select() clause
+     *
+     * @see https://github.com/cakephp/cakephp/issues/7913
+     * @return void
+     */
+    public function testEagerLoadingBelongsToManyLimitedFields()
+    {
+        $table = TableRegistry::get('Articles');
+        $table->belongsToMany('Tags');
+        $result = $table
+            ->find()
+            ->contain(['Tags' => function ($q) {
+                return $q->select(['id']);
+            }])
+            ->first();
+
+        $this->assertNotEmpty($result->tags[0]->id);
+        $this->assertEmpty($result->tags[0]->name);
+    }
 }