Problem with MANY_MANY and CGridView

Hi,

I’m just building my very first Yii application.

I have 3 tables:

user


uid <–PK

imie

nazwisko

zainteresowania


zid <–PK

nazwa

user_zainteresowania


uid <-- FK to user

zid <-- FK to zainteresowania

So we have many to many relation here, it is of course defined in models:

User model:




public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'zainteresowania' => array(self::MANY_MANY, 'Zainteresowania', 'user_zainteresowania(uid,zid)'),

		);



Zainteresowania model:




public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'user' => array(self::MANY_MANY, 'User', 'user_zainteresowania(zid,uid)'),

		);

	}



And CgridView:




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

	'id'=>'user-grid',

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

	'filter'=>$model,

	'columns'=>array(

		'uid',

		'imie',

		'nazwisko',

	

		array(            

            'name'=>'zainteresowania', 

            'value'=>'$data->zainteresowania->nazwa', 

		),

		

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>



Search function i User model:




public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('t.uid',$this->uid);

		//true na koncu oznacza, ze mozna filtrowac czesciami nazw

		$criteria->compare('t.imie',$this->imie,true);

		$criteria->compare('t.nazwisko',$this->nazwisko,true);

		

		


		//load the related table at the same time:

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


		

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

			'criteria'=>$criteria,

		));

	}




And I receive Error: htmlspecialchars() expects parameter 1 to be string, array given

What should I change to be able to view in CGridView data from both tables (user and zainteresowania) ?

This topic is widely discussed over the net, but I haven’t found satysfying solution…

Regards.

Hi alphacentauri,

"$data->zainteresowania" is an array of objects, not a single object, because your user can have many zainteresowanias.

So you may want to create some helper method to return a joined string of those zainteresowania’s nazwas in your user model.




<?php

	array(            

            'name'=>'zainteresowania', 

            'value'=>'$data->getJoinedZainteresowaniaNazwas()', 

	),

)); ?>



Also get rid of ‘zainteresowania’ from

the following code.




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

        ...

        array(            

            'name'=>'zainteresowania', 

            'value'=>'$data->zainteresowania->nazwa', 

        ),

        ...

)); ?>



You have to attach some ghost property instead.

Otherwise it may throw following error:

ok, now I’ve got it, I may prepare function

getJoinedZainteresowaniaNazwas()

which will return all zainteresowania.nazwa for specified user




 public function getJoinedZainteresowaniaNazwas()

	  {

		$names = array();

		if (is_array($this->zainteresowania)) {

		  for ($i = 0; $i < sizeof($this->zainteresowania); $i++) {

			array_push($names, CHtml::link(CHtml::encode($this->zainteresowania[$i]->nazwa),array('zainteresowania/view','id'=>$this->zainteresowania[$i]->zid)) );

		  }

		}

		if (sizeof($names) == 0)

		{

			array_push($names,"NONE");

		}

		return join("<BR>", $names);

	  } 



However this is not what I would like to do, because this will give me

all zainteresowania nazwas into one cell like in example:




uid       |imie       |nazwisko |   zainteresowania_nazwa|

----------------------------------------------------------

1         |Gerald     |Smith    |  zainter1              |

          |           |         |  zainter2              |

          |           |         |  zainter3              |

----------------------------------------------------------

2         |Ann        |Hayak    |  zainter1              |

          |           |         |  zainter4              |

----------------------------------------------------------



What I would like to achieve is every zainteresowanie in separate cell,

so CGridView would be somethink like this:




uid       |imie       |nazwisko |   zainteresowania_nazwa|

----------------------------------------------------------

1         |Gerald     |Smith    |   zainter1             |

----------------------------------------------------------

1         |Gerald     |Smith    |   zainter2             |

----------------------------------------------------------

1         |Gerald     |Smith    |   zainter3             |

----------------------------------------------------------

2         |Ann        |Hayak    |   zainter1             |

----------------------------------------------------------

2         |Ann        |Hayak    |   zainter4             |

----------------------------------------------------------



so I could use filter on zainteresowania…

Regards.

Create a view in the database;

In your case it may be like userZain.




CREATE ALGORITHM = UNDEFINED VIEW `userZain` AS SELECT imie,nazwisko,nazwa

FROM `user_zainteresowania`

INNER JOIN user

INNER JOIN zainteresowania

WHERE user_zainteresowania.uid = user.uid

AND user_zainteresowania.zid = zainteresowania.zid



Now you can create model for this view in GII.

No need for views and contoller.

Now you can in UserController.php create new action similar to actionAdmin.

You have to create also view files.

This can be only used for viewing. I think we can not do update or delete with this approach.