diff --git a/src/ORM/Query.php b/src/ORM/Query.php index 7f9c6b02424..291a8c6e78b 100644 --- a/src/ORM/Query.php +++ b/src/ORM/Query.php @@ -15,6 +15,7 @@ namespace Cake\ORM; use ArrayObject; +use Cake\Database\ExpressionInterface; use Cake\Database\Query as DatabaseQuery; use Cake\Database\ValueBinder; use Cake\Datasource\QueryTrait; @@ -510,15 +511,27 @@ public function count() { $query = $this->cleanCopy(); $counter = $this->_counter; - if ($counter) { $query->counter(null); return (int)$counter($query); } + $complex = ( + $query->clause('distinct') || + count($query->clause('group')) || + count($query->clause('union')) + ); + if (!$complex) { + // Expression fields could have bound parameters. + foreach ($query->clause('select') as $field) { + if ($field instanceof ExpressionInterface) { + $complex = true; + break; + } + } + } + $count = ['count' => $query->func()->count('*')]; - $complex = count($query->clause('group')) || $query->clause('distinct'); - $complex = $complex || count($query->clause('union')); if (!$complex) { $query->eagerLoader()->autoFields(false); diff --git a/tests/TestCase/ORM/QueryTest.php b/tests/TestCase/ORM/QueryTest.php index d243ae0cb5e..c10ab7e7387 100644 --- a/tests/TestCase/ORM/QueryTest.php +++ b/tests/TestCase/ORM/QueryTest.php @@ -1458,6 +1458,55 @@ public function testCountWithContain() $this->assertSame(3, $result); } + /** + * Test getting counts from queries with contain. + * + * @return void + */ + public function testCountWithSubselect() + { + $table = TableRegistry::get('Articles'); + $table->belongsTo('Authors'); + $table->hasMany('ArticlesTags'); + + $counter = $table->ArticlesTags->find(); + $counter->select([ + 'total' => $counter->func()->count('*') + ]) + ->where(['ArticlesTags.tag_id' => 1]) + ->where(['ArticlesTags.article_id = Articles.id']); + + $result = $table->find('all') + ->select([ + 'Articles.title', + 'tag_count' => $counter + ]) + ->matching('Authors', function ($q) { + return $q->where(['Authors.id' => 1]); + }) + ->count(); + $this->assertSame(2, $result); + } + + /** + * Test getting counts with complex fields. + * + * @return void + */ + public function testCountWithExpressions() + { + $table = TableRegistry::get('Articles'); + $query = $table->find(); + $query->select([ + 'admin' => $query->func()->concat( + ['Articles.title' => 'literal', 'test'], + ['string'] + ), + ]); + $query->where(['Articles.id' => 1]); + $this->assertCount(1, $query->all()); + $this->assertEquals(1, $query->count()); + } /** * test count with a beforeFind.