Search in nested tables of a MANY_MANY relationship

Hello all,

I have the following problem: in a model, called "Playlist", I want to display, order and search data from a different model, called "Canzoni".

There’s a MANY_MANY relationship between the two models. Inside the “Canzoni” search function, I additionally search inside two other relations: “Album” and “Artista”.

In the “Playlist” views, the data is correctly displayed and ordered, but the search doesn’t work at all. The mysql logs show that the query is built as the search fields are all blank, without the “WHERE LIKE” clause.

In the "Canzoni" views, the search is working correctly even for the related data.

My code is the following.

Playlist model, relations:


	public function relations()

	{

		return array(

			'canzonis' => array(self::MANY_MANY, 'Canzoni', 'canzoni_playlist(playlist_id, canzone_id)'),

		);

	}

Canzoni model, relations:


	public function relations()

	{

		return array(

			'album' => array(self::BELONGS_TO, 'Album', 'album_id'),

			'artista' => array(self::BELONGS_TO, 'Artisti', 'artista_id'),

			'playlists' => array(self::MANY_MANY, 'Playlist', 'canzoni_playlist(canzone_id, playlist_id)'),

		);

	}

Canzoni model, search:


	public function search()

	{

		$criteria=new CDbCriteria;		

	        $criteria->with=array(

				'album',

				'artista',

				);

		$criteria->together = TRUE;

		$criteria->compare('LOWER(titolo)',strtolower($this->titolo));

		$criteria->compare('LOWER(artista.nome)',strtolower($this->artista_id),TRUE);

	        $criteria->compare('LOWER(album.titoloalbum)',strtolower($this->album_id),TRUE);

                $criteria->compare('create_time',$this->create_time,TRUE);

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

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

		

		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

			'sort' => array (

				'defaultOrder'=>'artista.nome ASC',

				'attributes' => array (

					'titolo',

					'artista_id' => array (

						'asc'=>'artista.nome',

						'desc'=>'artista.nome DESC',

						),

					'album_id' => array (

						'asc'=>'album.titoloalbum',

						'desc'=>'album.titoloalbum DESC',

						),

					'create_time',

					'tot_esecuzioni',

					),

				),

		));

	}

In the Playlist views, I use the search function from the Canzoni model, this way:


$pageSize=Yii::app()->user->getState('pageSize',Yii::app()->params['defaultPageSize']);

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

	'id'=>'canzoni-playlist',

	'selectableRows'=>2,

	'showTableOnEmpty'=>false,

	'emptyText'=>'Nessun brano in questa playlist',

	'dataProvider'=>Canzoni::model()->with(array(

			'playlists'=>array(

				'condition'=>'playlists.id = :playlistID',

				'params'=>array(':playlistID' => $model->id),

				),

			)

		)->search(),

	'filter'=>Canzoni::model()->with(array(

			'playlists'=>array(

				'condition'=>'playlists.id = :playlistID',

				'params'=>array(':playlistID' => $model->id),

				),

			)

		),

	'columns' => array (

		'titolo'=>array(

			'name'=>'titolo',

			'type'=>'raw',

			'value'=>'CHtml::link(CHtml::encode($data->titolo), array("/canzoni/view", "id"=>$data->id))',

			'filter' => CHtml::activeTextField(Canzoni::model(), 'titolo'),

			'header'=>'Titolo',

		),

                array(

                        'name'=>'artista_id',

                        'header'=>'Artista',

                        'value'=>'$data->artista->nome',

                        'filter'=>CHtml::listData(Artisti::model()->findAll(array('order'=>'nome ASC')), 'nome','nome'),

                ),

                array(

                        'name'=>'album_id',

                        'header'=>'Album',

                        'value'=>'$data->album->titoloalbum',

                        'filter'=>CHtml::listData(Album::model()->findAll(array('order'=>'titoloalbum ASC')), 'titoloalbum','titoloalbum'),

                ),

	)

));

The dropdown menus have the right data inside them, only search isn’t working.

I also tried a different search function, adding the additional criteria inside it:




		$criteria->condition = "playlists.id = :playlistID";

		$criteria->params = array(':playlistID' => $playlistId);


....

all the other code is identical to the search posted above

...



Hints, anyone?

Let me know if some other information is needed.

Thanks in advance,

Andrea

[size=2][color="#006400"]/* moved to Yii 1.1 help forum /*[/color][/size]

Additional information: the sql query never changes. The following are the queries executed when I select the details of a playlist:




SET NAMES 'utf8'

SHOW COLUMNS FROM `playlist`

SHOW CREATE TABLE `playlist`

SELECT * FROM `playlist` `t` WHERE `t`.`id`=12 LIMIT 1

SHOW COLUMNS FROM `canzoni`

SHOW CREATE TABLE `canzoni`

SHOW COLUMNS FROM `artisti`

SHOW CREATE TABLE `artisti`

SELECT * FROM `artisti` `t` ORDER BY nome ASC

SHOW COLUMNS FROM `album`

SHOW CREATE TABLE `album`

SELECT * FROM `album` `t` ORDER BY titoloalbum ASC

SHOW COLUMNS FROM `canzoni_playlist`

SHOW CREATE TABLE `canzoni_playlist`

SELECT COUNT(DISTINCT `t`.`id`) FROM `canzoni` `t`  LEFT OUTER JOIN `canzoni_playlist` `playlists_playlists` ON (`t`.`id`=`playlists_playlists`.`canzone_id`) LEFT OUTER JOIN `playlist` `playlists` ON (`playlists`.`id`=`playlists_playlists`.`playlist_id`)  LEFT OUTER JOIN `album` `album` ON (`t`.`album_id`=`album`.`id`)  LEFT OUTER JOIN `artisti` `artista` ON (`t`.`artista_id`=`artista`.`id`)  WHERE (playlists.id = '12')


SELECT `t`.`id` AS `t0_c0`, `t`.`titolo` AS `t0_c1`, `t`.`durata` AS `t0_c2`, `t`.`path` AS `t0_c3`,

 `t`.`md5` AS `t0_c4`, `t`.`artista_id` AS `t0_c5`, `t`.`tot_esecuzioni` AS `t0_c6`, `t`.`album_id` 

AS `t0_c7`, `t`.`create_time` AS `t0_c8`, `t`.`update_time` AS `t0_c9`, `playlists`.`id` AS `t1_c0`, `playlists`.`nomeplaylist` AS `t1_c1`, `playlists`.`users_id` AS `t1_c2`, `playlists`.`status` 

AS `t1_c3`, `playlists`.`create_time` AS `t1_c4`, `playlists`.`update_time` 

AS `t1_c5`, `playlists`.`monday_status` AS `t1_c6`, `playlists`.`tuesday_status` 

AS `t1_c7`, `playlists`.`wednesday_status` AS `t1_c8`, `playlists`.`thursday_status` 

AS `t1_c9`, `playlists`.`friday_status` AS `t1_c10`, `playlists`.`saturday_status` 

AS `t1_c11`, `playlists`.`sunday_status` AS `t1_c12`, `album`.`id` 

AS `t2_c0`, `album`.`titoloalbum` 

AS `t2_c1`, `album`.`anno` AS `t2_c2`, `album`.`genere` AS `t2_c3`, `album`.`create_time` 

AS `t2_c4`, `album`.`update_time` AS `t2_c5`, `artista`.`id` AS `t3_c0`, `artista`.`nome` AS `t3_c1` 

FROM `canzoni` `t`  

LEFT OUTER JOIN `canzoni_playlist` `playlists_playlists` ON (`t`.`id`=`playlists_playlists`.`canzone_id`) 

LEFT OUTER JOIN `playlist` `playlists` ON (`playlists`.`id`=`playlists_playlists`.`playlist_id`)  

LEFT OUTER JOIN `album` `album` ON (`t`.`album_id`=`album`.`id`)  

LEFT OUTER JOIN `artisti` `artista` ON (`t`.`artista_id`=`artista`.`id`)  

WHERE (playlists.id = '12') ORDER BY artista.nome ASC LIMIT 50



If then I select an author or an artist from the dropdown menus, or I search a title, the additional constraint is not used: the queries are exactly the same as before. I would expect, for example, something like:

WHERE (playlists.id = ‘12’ AND artisti.id = ‘32’)

With firebug active, I see that the additional parameter is passed correctly.

Ciao,

Andrea

Never mind. I solved doing the reverse way. I now manage the playlists content inside the Canzoni view.