Problem Z Wyświetleniem Osobnego Modelu W Cgridview

Witam,

Jestem bardzo początkujący jeśli chodzi o Yii. ;) Do poprawienia mam pewną aplikację, ale natknąłem się na problem nie do obejścia. Istnieje tabela product, category i products_category. W modelach Product i Category oczywiście istnieją odpowiednie relacje (MANY_MANY), gdyż jeden produkt może być przypisany do wielu kategorii i na odwrót.

Produkty wyświetlane są poprawnie, natomiast problem pojawia się w panelu administratora. Akcja Admin wyświetla listę produktów. Dotychczas produkt przypisany był do jednej kategorii i rozwiązane to było jednym polem ‘category_id’ w tabeli product.

Teraz przy wyświetlaniu produktów w kolumnie ‘kategorie’ muszę wyświetlić wszystkie kategorie, a nie tylko jedną. Na chwilę obecną wygląda to tak:

actionAdmin():


	public function actionAdmin()

	{            

                $dataProvider=new CActiveDataProvider('Product', array(

                        'criteria'=>array(

                            'condition'=>'t.category_id=category.id',

                            'with'=>'category',

                            'order'=>'t.sort_order ASC, t.id DESC',

                            'together'=>true

                        )

                ));            

            

		$this->render('admin',array(

                        'dataProvider'=>$dataProvider,

		));

	}

widok admin.php


<?php $this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'product-grid',

	'dataProvider'=>$dataProvider,

	'columns'=>array(

		'id',

		'name',

                array(

                    'name'=>'image',

                    'type'=>'html',

                    'value'=>"CHtml::link(CHtml::image(Yii::app()->request->baseUrl.'/'.Product::IMAGES_PATH.'small/'.\$data->image, \$data->image), Yii::app()->request->baseUrl.'/'.Product::IMAGES_PATH.'big/'.\$data->image, array('class'=>'inline'))",

                    //'filter'=>false,

                ),

                array(

                    'name'=>'category.name_pl',

                ),

W jaki sposób w polu ‘value’ dla kategorii wylistować wszystkie kategorie korzystając z widgetu CGridView?

Z góry dzięki za pomoc. :)

Tak na szybko (dopasuj do swoich danych):

Tabele:




product:

id: PK

name: VARCHAR

description: TEXT


category:

id: PK

name: VARCHAR


product_category

id: PK

productId: FK to product

categoryId: FK to category



  1. W modelu Product dodaj relacje:



public function relations() {

    return array(

        //..

        'productCategories' => array(self::HAS_MANY, 'ProductCategory', 'productId'),            

        'categories' => array(

            self::HAS_MANY, 'Category', 'categoryId', 'through' => 'productCategories',

            'alias' => 'c', 'order' => 'c.name ASC',

        ),

    );

}



  1. Dodaj klasę (w protected/widgets/grid/)



<?php

Yii::import('zii.widgets.grid.CDataColumn');


class EManyToManyDataColumn extends CDataColumn {

    

    public $relatedFieldName;

    

    public function init() {

        parent::init();

        if ($this->relatedFieldName === null) {

	    throw new CException(

                Yii::t('zii', 'Variable "relatedFieldName" must be specified for EManyToManyDataColumn.')

            );

        }

    }

    

    protected function renderDataCellContent($row, $data) {

        $value = '';

        $relatedFieldName = $this->relatedFieldName;

        $relatedData = $this->evaluateExpression($this->value, array('data'=>$data,'row'=>$row));

        if (is_array($relatedData)) {            

            foreach ($relatedData as $relatedRow) {

                $value .= $relatedRow->$relatedFieldName . '<br/>';

            }

        }

        echo $value === '' ? $this->grid->nullDisplay : $this->grid->getFormatter()->format($value, 'raw');

    }

}

?>



  1. Dodaj kolumnę do CGridView:



    array(

       'class'=>'application.widgets.grid.EManyToManyDataColumn',

       'value'=>'$data->categories', //relacja do kategorii - zdefiniowana w relations()

       'relatedFieldName'=>'name',

    ),



Powinno działać, choć trzeba jeszcze pokombinować z zapytaniami…

Jako że lubię wiedzieć co i jak, mam pytanie, czy relacja którą podałeś nie może być określona w ten sposób:


'category' => array(self::MANY_MANY, 'Category', 'products_category(pid,cid)'),

? Myślałem że takie określenie relacji wystarczy do wszystkich zapytań relacyjnych.

Możesz też w modelu dodać funkcję


public function getKategorie(){

  $val = '';

  foreach($this->categories as $cat){

    $val .= $cat->name;

    //tu możesz dowolnie sformatować wartość wyjściową

  }

  return $val;

}

jako kolumnę w CGridView podajesz:


 'columns'=>array(

       ...

      'kategorie',

       ...

 )

Kod niesprawdzany ale chyba coś w tym stylu powinno zadziałać.

categories to w tym przypadku zdefiniowana relacja.