Browse Source

Merge pull request #5961 from cakephp/issue-5955

Remove fields from count() queries when associations are contained.
Mark Story 11 years ago
parent
commit
f786cbc6b9
4 changed files with 52 additions and 2 deletions
  1. 5 0
      src/ORM/Association.php
  2. 24 1
      src/ORM/EagerLoader.php
  3. 1 0
      src/ORM/Query.php
  4. 22 1
      tests/TestCase/ORM/QueryTest.php

+ 5 - 0
src/ORM/Association.php

@@ -640,6 +640,11 @@ abstract class Association
         $fields = $surrogate->clause('select') ?: $options['fields'];
         $target = $this->_targetTable;
         $autoFields = $surrogate->autoFields();
+
+        if ($query->eagerLoader()->autoFields() === false) {
+            return;
+        }
+
         if (empty($fields) && !$autoFields) {
             if ($options['includeFields'] && ($fields === null || $fields !== false)) {
                 $fields = $target->schema()->columns();

+ 24 - 1
src/ORM/EagerLoader.php

@@ -96,6 +96,15 @@ class EagerLoader
     protected $_joinsMap = [];
 
     /**
+     * Controls whether or not fields from associated tables
+     * will be eagerly loaded. When set to false, no fields will
+     * be loaded from associations.
+     *
+     * @var bool
+     */
+    protected $_autoFields = true;
+
+    /**
      * Sets the list of associations that should be eagerly loaded along for a
      * specific table using when a query is provided. The list of associated tables
      * passed to this method must have been previously set as associations using the
@@ -135,6 +144,20 @@ class EagerLoader
     }
 
     /**
+     * Set whether or not contained associations will load fields automatically.
+     *
+     * @param bool $value The value to set.
+     * @return bool The current value.
+     */
+    public function autoFields($value = null)
+    {
+        if ($value !== null) {
+            $this->_autoFields = (bool)$value;
+        }
+        return $this->_autoFields;
+    }
+
+    /**
      * Adds a new association to the list that will be used to filter the results of
      * any given query based on the results of finding records for that association.
      * You can pass a dot separated path of associations to this method as its first
@@ -294,7 +317,7 @@ class EagerLoader
             $config = $loadable->config() + [
                 'aliasPath' => $loadable->aliasPath(),
                 'propertyPath' => $loadable->propertyPath(),
-                'includeFields' => $includeFields
+                'includeFields' => $includeFields,
             ];
             $loadable->instance()->attachTo($query, $config);
         }

+ 1 - 0
src/ORM/Query.php

@@ -507,6 +507,7 @@ class Query extends DatabaseQuery implements JsonSerializable
         $complex = $complex || count($query->clause('union'));
 
         if (!$complex) {
+            $query->eagerLoader()->autoFields(false);
             $statement = $query
                 ->select($count, true)
                 ->autoFields(false)

+ 22 - 1
tests/TestCase/ORM/QueryTest.php

@@ -1446,6 +1446,27 @@ class QueryTest extends TestCase
     }
 
     /**
+     * Test getting counts from queries with contain.
+     *
+     * @return void
+     */
+    public function testCountWithContain()
+    {
+        $table = TableRegistry::get('Articles');
+        $table->belongsTo('Authors');
+
+        $result = $table->find('all')
+            ->contain([
+                'Authors' => [
+                    'fields' => ['name']
+                ]
+            ])
+            ->count();
+        $this->assertSame(3, $result);
+    }
+
+
+    /**
      * test count with a beforeFind.
      *
      * @return void
@@ -1871,7 +1892,7 @@ class QueryTest extends TestCase
 
     /**
      * Tests that getting results from a query having a contained association
-     * will no attach joins twice if count() is called on it afterwards
+     * will not attach joins twice if count() is called on it afterwards
      *
      * @return void
      */