Problem z CGridView (odwołanie kolumny z relacji wiele-do-wiele)

Cześć:)

Mam problem z widgetem CGridView, a dokładniej z odwołaniem się do wartości kolumny z relacji wiele-do-wiele.


'value'=>'$data->groups->group'

Framework zwraca błąd:


Trying to get property of non-object


Brak kodu źródłowego

Gdy wywołam normalnie (nie przez wigdet);


$user = User::model()->findByPK('1'); $user->groups

Wynik jest poprawny - zwracana jest tablica obiektów group.

Męczę się w tym już kilka godzin i nie mogę dojść do ładu, dlatego proszę Was o pomoc.

Relacja jest zdefiniowana:


	

public function relations()

{

	return array(

		'groups' => array(self::MANY_MANY, 'Group', 'users_groups(id_user, id_group)'),		

	);

}



Metoda search:




public function search()

{

	$criteria=new CDbCriteria;


	$criteria->compare('login',$this->login,true);


	$criteria->compare('name',$this->name,true);


	$criteria->compare('surname',$this->surname,true);


	$criteria->compare('email',$this->email,true);


	$criteria->compare('lastActive',$this->lastActive,true);


	$criteria->compare('active',$this->active);


	$criteria->with = array('groups');


	return new CActiveDataProvider(get_class($this), array(

		'criteria'=>$criteria,

	));

}



Widget:




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

	'id'=>'user-grid',

	'dataProvider'=>$model->search(),

        'filter'=>$model,

		'columns'=>array(

             .

			 .

			 .

                array(

                    'filter'=>CHtml::listData(Group::model()->findAll(),'id','group'),

                    'header'=>'Grupy',

                    'name'=>'groups.group', //? nie wiem jak sie odwolac

                    'value'=>'$data->groups->group' // tu zwraca blad

                ),

            .

			.

			.

	),

)); ?>



Baza w zarysie ogółnym wygląda następująco:

Tabela users

id (PK) int(11) 


login 	varchar(64) 	


passwd 	varchar(40) 	


name 	varchar(64) 	


surname 	varchar(64) 	


email 	varchar(64) 


lastActive 	datetime 		


active 	tinyint(1) 	

Tabela users_groups

id_user  (PK)	int(11)  	 	  


id_group (PK)	smallint(6) 

Tabela groups

id (PK) smallint(6)  


group 	varchar(64)

Cześć! Pewnie już sobie poradziłeś, ale może ktoś inny będzie miał podobny problem.

Dzieje się tak dlatego że


$data->groups

to nie obiekt a tablica obiektów (grup do których należy user), stąd błąd. Poniższe powinno zadziałać:


$data->groups[0]->group

Oczywiście wypisana zostanie jedynie pierwsza wartość :). Lepiej zrobić tak:


'value' => 'implode("<br/>",$data->groups)'

oczywiście uprzednio uzupełniwszy klasę Group o metodę __toString




public function  __toString() {

   return $this->group;

}



Pozdro :)

dzięki krzysiek:) Poradziłem sobie, ale Twój sposób jest o wiele bardziej elegancki:)

Korzystają z farta:) wiesz może jak zrobić, aby Grid filtrował po tych grupach?

W tablicy column ustawiłem widgetu:




array(

   'filter'=>CHtml::listData(Group::model()->findAll(),'id','group'),

   'header'=>'Grupy',

   'name'=>'groups',

   'value'=>'implode(", ",$data->groups)',

),



name ustawiłem na wartość groups, choć nie wym czy przypadkiem do nie powinienem dodać nowej właściwości do modelu User (np. groupId)?

W metodzie Rules dodałem:




array('groups', 'safe', 'on'=>'search'),



Dodatkowo w search:




$criteria->compare('g.id',$this->groups);

$criteria->with = array('groups');



Całośc zwraca:




1054 Unknown column 'groups.id' in 'where clause'



Najpierw fw wywołuje

[sql]

Querying SQL: SELECT COUNT(DISTINCT t.id) FROM users t LEFT OUTER

JOIN users_groups groups_g ON (t.id=groups_g.id_user) LEFT

OUTER JOIN groups g ON (g.id=groups_g.id_group) WHERE

(g.id=:ycp0). Bind with parameter :ycp0=‘2’

[/sql]

a później (tu pojawia się błąd):

[sql]

Error in querying SQL: SELECT t.id AS t0_c0, t.login AS t0_c1,

t.passwd AS t0_c2, t.name AS t0_c3, t.surname AS t0_c4,

t.email AS t0_c5, t.lastActive AS t0_c6, t.active AS

t0_c7 FROM users t WHERE (g.id=:ycp0) LIMIT 10. Bind with parameter

:ycp0=‘2’

[/sql]

?? :(((

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

Też miałem (mam?) z tym problem. Jak widać w zapytaniach pierwsze dotyczące ilości rekordów idzie z joinem, drugie już nie. Niestety, nie udało mi się wymusić joina w drugim zapytaniu. Jeżeli ktoś wie jak to zrobić to również byłbym wdzięczny za hinta :).

Ja obszedłem to za pomocą podzapytania, patrz niżej.

Ja dodałbym do klasy User pole o nazwie np. ‘filter_group’ i taki też nadał name w widżecie.




public $filter_group;



Oznacz jako ‘safe’ dla odpowiedniego scenariusza, a w metodzie search() dodaj co następuje przed return:




if(is_string($this->filter_group) && strlen($this->filter_group) > 0) {

    $criteria->params[':groupname'] = $this->filter_group;

    $criteria->addCondition("t.id IN (SELECT ug.id_user FROM `users_groups` ug JOIN `groups` g ON ug.id_group = g.id WHERE g.group LIKE :groupname)");

}


return new CActiveDataProvider...



Powinno zadziałać. :)

Trzeba przy tym uważać żeby nie nadpisać w tablicy params żadnego parametru dodawanego przez Yii. Na szczęście mają one dość egzotyczne nazwy więc nie powinno być problemu.

dzięki za szybką odpowiedź i pomoc:) możliwe, że trochę poczekamy na jakąś wskazówkę…