There is a few cases that you want more of one CActiveDataProvider displayed in one CGrideView How to do that?
Obviusly the CActiveDataProviders have to same schema (contains same columns)
In your controller set the two (or more) CActiveDataProvider like that
$prov1 = new CActiveDataProvider('Post', array(
'criteria' => array(
'condition' => 'id<3'
)
));
$prov2 = new CActiveDataProvider('Post', array(
'criteria' => array(
'condition' => 'id>3'
)
));
Obviusly in this case you could use 'condition' => 'id>3 or id<3' buτ let us assume we want the CActiveDataProvider seperated for another purpose.
Now we have to merge these data in one Provider through array
$records = array();
for ($i = 0; $i < $prov1->totalItemCount; $i++) {
$data = $prov1->data[$i];
array_push($records, $data);
}
for ($i = 0; $i < $prov2->totalItemCount; $i++) {
$data = $prov2->data[$i];
array_push($records, $data);
}
//or you could use $records=array_merge($prov1->data , $prov2->data);
$provAll = new CArrayDataProvider($records,
array(
'sort' => array( //optional and sortring
'attributes' => array(
'id',
'title'
),
),
'pagination' => array('pageSize' => 10) //optional add a pagination
)
);
//render a view
$this->render('custom',array('provAll' => $provAll));
in custom.php add the CGridView widget
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $provAll,
'columns' => array('id', 'title'),
));
Both of two CActiveDataProvider data will be displayed in CGridView
Thanks
Dear KonApaz
Thanks for sharing the tip.
So things are ultimately boiling down to CArrayDataProvider. As most of us are comfortable with PHP rather than SQL.
I want to share couple of things.
1.We can get the $records in the following way.
$records=$prov1->data + $prov2->data; //+ is array union operator.
2.If two data providers are sharing the same id(PK), it is better to declare the property keyField as false.
$provAll = new CArrayDataProvider($records, array( 'keyField'=>false, 'sort' => array( //optional and sortring 'attributes' => array( 'id', 'title',), ), 'pagination' => array('pageSize' => 10) //optional add a pagination ) );
Regards.
About array union operator
Hi seenivasan
About array union operator.
It is not working properly because $prov1->data and $prov2->data return based-zero indexes array, so all $prov1->data overrided by $prov2->data.
Instead of that I recommend:
I check 'keyField'=>false when there are duplicates and not works! (although the documentation http://www.yiiframework.com/doc/api/1.1/CArrayDataProvider prompts that! Did you test it? )
In any case thanks for your comment! :)
Really Sorry!
Dear My Friend
You are absolutely correct.
I thought array union operator will just do the things. But it eliminates records sharing common keys.
If two data provider sharing common primary key values, it is advised to declare the keyField as
false.
This way arrayDataProvider assigns a unique value based on the index position of individual record.
By doing that yiiGridView.getKey assigns a unique number to each row in grid.
That was helpful to me when I used PHP arrays as raw data.
If you have better inputs on this, let me know .
Regards.
About union operator
Hi seenivasan
don't worry!
All comments and opinions are welcome!
Having variety of knowledge from other members you could improve each other!
So thanks all of you for comments, opinions and corrections! :)
CActiveDataProvider will also work
One of the nice thing about the CActiveDataProvider is that it can use all kind of data from the model automatically. Like labels.
I have an i18n site and needed the labels in many languages. This was handled in the models. But when I used the CArrayDataProvider this is not working (right away..?). But then it hits me that the 'data' attribute of a Provider can also be set! So I tried the following and it works!
$records=array_merge($prov1->data , $prov2->data); $provAll = new CActiveDataProvider('Post',array( 'data'=>$records, ));
RE: #15955
Hi ametad
In this wiki CActiveDataProvider get from CActiveDataProvider only the data of CActiveRecord.
After use the zii.widgets.grid.CGridView directly.
So if you want many languages header-title you could use
$this->widget('zii.widgets.grid.CGridView', array( 'dataProvider' => $provAll, 'columns' => array( 'id', array('header'=>Yii::t('yourI18Ncategory', 'title') , value=>$data['title']), ), ));
Use an array to display records from two different tables
This is a very nice wiki.
Just a note:
You could also have $prov1 and $prov2 containing data from different tables and then merge them into an array.
For example: I have a table containing records of downloadable documents linked to calendar events. Another table contains records of downloadable documents linked to curriculum units. I want to display all records of downloadable documents in a single gridview.
Use the following type of code to extract the $prov1 data into an array (not into models). Repeat the code for $prov2 and make sure its array contains the same keys.
$records = array(); for ($i = 0; $i < $prov1->totalItemCount; $i++) { $data = $prov1->data[$i]; $fields = array( 'compId' => 'a'.$data->trn35_id.$data->rel_trn35_adm6->adm6_id, 'adm6Id' => $data->rel_trn35_adm6->adm6_id, 'date' => $data->trn35_from_udo, 'usage' => ar_adm6::model()->getAdm6Usage( $data->rel_trn35_adm6->adm6_hc_usage), 'code' => $data->rel_trn35_adm6->adm6_cd, 'cat1' => $data->rel_trn35_adm6['rel_adm6_adm14_1']['adm14_desc'], 'cat2' => $data->rel_trn35_adm6['rel_adm6_adm14_2']['adm14_desc'], 'desc' => $data->rel_trn35_adm6->adm6_desc, 'fname' => $data->rel_trn35_adm6->adm6_file_name, ); array_push($records, $fields); }
You can sort the records using the array KEYS.
$sort = new CSort; $sort->attributes = array( 'publicVariable'=>array( 'asc' => "adm6Id ASC", 'desc' => "adm6Id DESC", ), );
Generate dataprovider
$pageSize = count($records); return new CArrayDataProvider($records, array( 'id' => 'downloadDp', 'keyField' => 'compId', 'sort' => $sort, 'pagination'=> array( 'pageSize'=>$pageSize, ), ) );
In the gridview the column will look like this:
array( 'name' => 'publicVariable', 'header' => CHtml::encode($model->getAttributeLabel('publicVariable')), 'type' => 'raw', 'value' => 'CHtml::encode($data["adm6Id"])', ),
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.