multiple CActiveDataProviders in one CGridView


This wiki article has not been tagged with a corresponding Yii version yet.
Help us improve the wiki by updating the version information.

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,
                            '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

Total 5 comments

#15955 report it
ametad at 2014/01/03 11:24am
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(
#13829 report it
KonApaz at 2013/06/29 05:07am
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! :)

#13795 report it
seenivasan at 2013/06/26 11:23am
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 .


#13773 report it
KonApaz at 2013/06/24 07:18pm
About array union operator

Hi seenivasan

About array union operator.

$records=$prov1->data + $prov2->data;

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:

$records=array_merge($prov1->data , $prov2->data);

I check 'keyField'=>false when there are duplicates and not works! (although the documentation prompts that! Did you test it? )

In any case thanks for your comment! :)

#13770 report it
seenivasan at 2013/06/24 02:11pm

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,
                            'sort' => array( //optional and sortring
                                'attributes' => array(
                                    'id', 'title',),
                            'pagination' => array('pageSize' => 10) //optional add a pagination


Leave a comment

Please to leave your comment.

Write new article