Search code examples
phpyiihas-manycgridview

Yii CGridView, I can't display fields form other model using HAS_MANY relationship


I have a HAS_MANY relation between 2 models, i use bookID as foreign key

model 1 - Importedbooks, Importedbooks can have many CountryOfImport

public function relations()
{ 
    return array(
       'CountryOfImportObj'=>array(self::HAS_MANY, 'CountryOfImport', 'bookID')
    );
}    

model 2 CountryOfImport, CountryOfImport belongs to Importedbooks

public function relations()
{ 
    return array(
        'ImportBooksObj'=>array(self::BELONGS_TO, 'Importedbooks', 'bookID')
    );
}

Now, For my CGridView i am using a model->search()of the Importedbooks model as my dataProvider, From here is where i get stuck.

CGridView

 $data = $model->search();
 $data->setPagination(array('pageSize'=>'5'));
 $data->criteria->addCondition('active = "yes"');  
 $this->widget('zii.widgets.grid.CGridView', array(
           'dataProvider'=>$data
           ,'filter'=>$model 
           ,'pager'=>array('header'=>'')  
           ,'columns'=>array(  
                    'id',
                    'bookYear',
                    'bookTitle',
                    'DISPLAY VALUE FROM OTHER model HERE'
                    )
           )
         );

DataProvider of the Imported books model, i'm using this as my data provider for the grid

public function search()
{ 
    $criteria=new CDbCriteria;               
    $criteria->compare('id',$this->id);
    $criteria->compare('bookID',$this->bookID);
    $criteria->compare('countryName',$this->countryName,true);
    return new CActiveDataProvider($this, array(
        'criteria'=>$criteria,
    ));
}

The relation works because i can use below code in my controller to get a field(countryName) from the other model

$model = Importedbooks::model()->with('CountryOfImportObj')->findbyPK(3);
print_r($model->CountryOfImportObj[0]->countryName);

Solution

  • Such as Importedbooks have many CountryOfImport, in one row you must show or all country names or concreet names depending on ID or countryName or some other attribute.

    You can pass anonymous function as value:

    'columns' => array(  
        'id',
        'bookYear',
        'bookTitle',
        array(
           'header' => 'Countries',
           'type' => 'raw',
            // if you have defined counrtyName attribute in  'Importedbooks' model, if not you can remove this row
            // also CGridView 'uses' attribute 'name' for filtering or sorting
           'name' => 'countryName',
           'value' => function($data, $row) { //$data is item of DataProvider, $row is number of row (starts from 0)
               $countries = CHtml::listData((array)$data->CountryOfImportObj, 'id', 'countryName');
               return implode(', ', $countries);
           }
        )
    )
    

    If you want to filter or sort by external attributes too, you must "declare them"

    Thanks!