On clause does not apply to MANY_MANY relations

Say I have a table [font="Courier New"]songs[/font], a table [font="Courier New"]genres[/font] and since these two have a many-many relation, I also have a junction table [font="Courier New"]song_genre[/font].

But I also want to express that one of each song’s genres is its primary genre. This is handily done with an [font=“Courier New”]is_primary[/font] column in [font=“Courier New”]song_genre[/font].

Now I’d like to have a relation in my Song model that delivers the song’s primary genre.


class Song extends CActiveRecord

{

	public function relations()

	{

		return array(

			'genres'  => array(

				self::MANY_MANY, 

				'Genre', 

				'dj_has_genre(dj_user_id,genre_id)'

			),

			'primaryGenre' => array(

				// MANY_MANY because Yii can't know that a song can have only one primary genre

				self::MANY_MANY, 

				'Genre', 

				'dj_has_genre(dj_user_id,genre_id)',

				'on' => 'dj_has_genre.is_primary=1',

			),

		);

	}

...

}

But this is forbidden:

Now why would Yii forbid this?

Did you try it? I was in a thread the other day and the guy solved his problem with an on clause pertaining to a many:many. I think those docs are out of date on that.

If not just write a through relationship that emulates a many:many and applies the on clause.

I did and I was getting a “Column not found” SQL error. Very odd because the column it says it can’t find is clearly there.

Then I tried changing [font=“Courier New”]‘on’ => ‘song_has_genre.is_primary=1’[/font] to [font=“Courier New”]‘on’ => ‘is_primary=1’[/font] and now it works!

So when the guide says "on: the ON clause. The condition specified here will be appended to the joining condition using the AND operator. Column names referenced in this option should be disambiguated. This option does not apply to MANY_MANY relations," the last two of those three sentences are incorrect.

This seems like a skill worth learning.

Would I need a model for the junction table to make this work?

You have to give a model name, making it a little more work, that’s why in probably 90% (made up statistic) of cases you just want use an ‘on’ clause.