I have a strange problem with CListView and CActiveDataProvider.
When I’m trying to list items in clistview, in some pages between first and last page, items are less than page size!
I don’t even know where to dig for this problem.
Anyone’s guidance will be appreciated!
krowe
(Kevin)
May 29, 2013, 7:25pm
2
It’s been awhile but I believe that because of the way CActiveDataProvider retrieves data it will only count records in the primary table. If your query has a condition which limits the result because of the value of a child table it will do what you are explaining. IMHO, The easiest way to fix this is the create a view in your DB with what you want in it and then use that instead of a complicated Yii query.
krowe is right. Post your criteria code and someone can assist. I had the same problem using a many_many relationship. Also, take a look here - http://www.yiiframework.com/wiki/428/drills-search-by-a-has_many-relation/#hh14
Notice the select, together, and group.
Matt
Here’s the code that I’m working on:
in this I use a class for searching in my website, and this is search function of this class.
relation between product and catalog, product tag is HAS_MANY.
public function search($q) {
/**
* base
*/
$criteria = new CDbCriteria();
$criteria->addCondition('t.publish="yes"');
$criteria->order = 't.creationDate DESC';
/**
* keyword
*/
if ($q['keyword']) {
$words = array_map('trim', explode(' ', $q['keyword']));
$criteriaKeyword = new CDbCriteria();
if (is_array($words)) {
foreach ($words as $word)
{
$criteriaKeyword->compare('t.title', $word, true, 'OR');
$criteriaKeyword->compare('t.description', $word, true, 'OR');
$criteriaKeyword->compare('catalogs.title', $word, true, 'OR');
$criteriaKeyword->compare('catalogs.description', $word, true, 'OR');
$criteriaKeyword->compare('tags.name', $word, true, 'OR');
}
}
if ($criteriaKeyword)
{
$criteria->with[] = 'catalogs';
$criteria->with[] = 'tags';
$criteria->together = true;
$criteria->mergeWith($criteriaKeyword, true);
}
}
/**
* category
*/
if ($q['category']) {
$criteriaCategory = new CDbCriteria();
$criteriaCategory->compare('productCategories.categoryId', $q['category']);
if ($criteriaCategory) {
$criteria->with[] = 'productCategories';
$criteria->together = true;
$criteria->mergeWith($criteriaCategory, true);
}
}
/**
* language
*/
if ($q['language']) {
$criteriaLanguage = new CDbCriteria();
$criteriaLanguage->compare('catalog.languageId', $q['language']);
if ($criteriaLanguage) {
$criteria->with[] = 'catalogProducts';
$criteria->with[] = 'catalogProducts.catalog';
$criteria->together = true;
$criteria->mergeWith($criteriaLanguage, true);
}
}
return $dataProvider = new CActiveDataProvider('Product', array(
'criteria'=>$criteria,
'totalItemCount'=>500,
'pagination'=>array(
'pageSize'=>20,
),
));
}
in controller i have just render a view and send this search function as variable to view!
Haven’t tested it but something like this:
public function search($q)
{
/**
* base
*/
$criteria = new CDbCriteria();
$criteria->addCondition('t.publish="yes"');
$criteria->order = 't.creationDate DESC';
// group by Product's id
$criteria->group = 't.id';
/**
* keyword
*/
if ($q['keyword'])
{
$words = array_map('trim', explode(' ', $q['keyword']));
$criteriaKeyword = new CDbCriteria();
if (is_array($words))
{
foreach ($words as $word)
{
$criteriaKeyword->compare('t.title', $word, true, 'OR');
$criteriaKeyword->compare('t.description', $word, true, 'OR');
$criteriaKeyword->compare('catalogs.title', $word, true, 'OR');
$criteriaKeyword->compare('catalogs.description', $word, true, 'OR');
$criteriaKeyword->compare('tags.name', $word, true, 'OR');
}
}
if ($criteriaKeyword)
{
$criteria->with[] = array(
'catalogs' => array(
'together' => true,
'select' => false
),
'tags' => array(
'together' => true,
'select' => false
)
);
$criteria->mergeWith($criteriaKeyword, true);
}
}
/**
* category
*/
if ($q['category'])
{
$criteriaCategory = new CDbCriteria();
$criteriaCategory->compare('productCategories.categoryId', $q['category']);
if ($criteriaCategory)
{
$criteria->with[] = array(
'productCategories' => array(
'together' => true,
'select' => false
)
);
$criteria->mergeWith($criteriaCategory, true);
}
}
/**
* language
*/
if ($q['language'])
{
$criteriaLanguage = new CDbCriteria();
$criteriaLanguage->compare('catalog.languageId', $q['language']);
if ($criteriaLanguage)
{
$criteria->with[] = array(
'catalogProducts' => array(
'together' => true,
'select' => false
),
'catalogProducts.catalog' => array(
'together' => true,
'select' => false
)
);
$criteria->mergeWith($criteriaLanguage, true);
}
}
return $dataProvider = new CActiveDataProvider('Product', array(
'criteria'=>$criteria,
'totalItemCount'=>500,
'pagination'=>array(
'pageSize'=>20,
),
));
}
Matt