Skip to content
Permalink
Browse files

Adding the ability to register a callback funciton to override the

results of Query::count()
  • Loading branch information...
lorenzo committed Jan 23, 2014
1 parent 9f8505f commit d96d155354f7cff07af54037c13cb1ea39962f37
Showing with 57 additions and 1 deletion.
  1. +36 −1 src/ORM/Query.php
  2. +21 −0 tests/TestCase/ORM/QueryTest.php
@@ -143,6 +143,14 @@ class Query extends DatabaseQuery {
*/
protected $_cache;
/**
* A callable function that can be used to calculate the total amount of
* records this query will match when not using `limit`
*
* @var callable
*/
protected $_counter;
/**
* Constuctor
*
@@ -873,19 +881,46 @@ public function first() {
public function count() {
$query = clone $this;
$query->limit(null);
$query->offset(null);
$counter = $this->_counter;
if ($counter) {
$query->counter(null);
return (int)$counter($query);
}
// Forcing at least one field to be selected
$query->select($query->newExpr()->add('1'));
$statement = $this->connection()->newQuery()
->select(['count' => $query->func()->count('*')])
->from(['source' => $query])
->from(['count_source' => $query])
->execute();
$result = $statement->fetch('assoc')['count'];
$statement->closeCursor();
return (int)$result;
}
/**
* Registers a callable function that will be executed when the `count` method in
* this query is called. The return value for the function will be set as the
* return value of the `count` method.
*
* This is particularly useful when you need to optimize a query for returning the
* count, for example removing unnecessary joins, removing group by or just return
* an estimated number of rows.
*
* The callback will receive as first argument a clone of this query and not this
* query itself.
*
* @param callable $counter
* @return Cake\ORM\Query
*/
public function counter($counter) {
$this->_counter = $counter;
return $this;
}
/**
* Toggle hydrating entites.
*
@@ -1515,6 +1515,27 @@ public function testCountWithGroup() {
$this->assertEquals(2, $result);
}
/**
* Tests that it is possible to provide
*
* @return void
*/
public function testCountWuthCustomCounter() {
$table = TableRegistry::get('articles');
$query = $table->find('all');
$query
->select(['author_id', 's' => $query->func()->sum('id')])
->where(['id >' => 2])
->group(['author_id'])
->counter(function($q) use ($query) {
$this->assertNotSame($q, $query);
return $q->select([], true)->group([], true)->count();
});
$result = $query->count();
$this->assertEquals(1, $result);
}
/**
* Test update method.
*

0 comments on commit d96d155

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