I’m using CActiveDataProvider with CDbCriteria to search through some related models, using multiple related models. The code to generate the results is as below:

$criteria->select = ‘*, ( 3959 * acos( cos( radians(’ . $latitude . ‘) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(’ . $longitude . ‘) ) + sin( radians(’ . $latitude . ‘) ) * sin( radians( latitude ) ) ) ) * 1.609344 AS distance’; //Basically just calculating distance from an input point

The search works fine and gets the results as expected. The problem is that the CListview reports the number of results correctly, but shows pagination anyways. For example: 'Displaying 1-7 of 31 results, and pagination is shown. Clicking on pages 2, 3, 4 show no results.

I would guess that it is to do with the ‘together’ parameter for the CDbCriteria (although I don’t see it in the code you give).

If ‘together’ is true then the CActiveDataProvider pulls everything together in one big query, which may mean multiple lines per model, thus giving the erroneous count that you notice. If you set ‘together’ => false, then the CActiveDataProvider should execute one query for the model table, then additional queries for the join tables, and collate all that data itself (so giving the right count, hopefully).

I tried setting together to both true and false, but there was no change in the results. Is there any way I can fetch the number of results that’s shown in the summary in the model?

I’m trying to use $dataProvider->setTotalItemCount($numberResults); right before return $dataProvider in the model. Any idea how I might do this?

Edit:

OK, it’s hacky, but here’s what I’ve done -

$numResults = count($dataProvider->getData());
if($numResults == 0) {
$criteria->condition = '1=0';
//I don't know how to return null <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/tongue.gif' class='bbc_emoticon' alt=':P' />
return new CActiveDataProvider('Store', array('criteria'=>$criteria));
}
$dataProvider->setTotalItemCount(count($dataProvider->getData()));

If the $numberResults is 0, $dataProvider->setTotalItemCount(count($dataProvider->getData())); doesn’t work, so I’m forcing a null result.

)… till I had aggregated data > 10 items. In that case, you realize that the pager in the footer is still incorrect, and the header is in fact {x MOD pageSize}, i.e. the first page would be ‘1-10 of 10’, and the last page ‘1-x of 10’.

Anyway, I digged the whole Web looking for a solution

I nearly found what I thought was the solution with

I had similar problem when using group in query. There’s my solution:

Add class CActiveDataProviderEx to your project:

class CActiveDataProviderEx extends CActiveDataProvider {
protected function calculateTotalItemCount() {
$baseCriteria=$this->model->getDbCriteria(false);
if ($baseCriteria!==null)
$baseCriteria=clone $baseCriteria;
//You can get real records count only in this way (when you use JOIN and GROUP BY)
$count=count($this->model->findAll($this->getCriteria()));
$this->model->setDbCriteria($baseCriteria);
return $count;
}
}

and use it instead CActiveDataProvider:

$productCategory = new CActiveDataProviderEx('ProductCategory', ...);