How to get model ID in AR relations?

I need to get the current model ID to set the conditions of a MANY_MANY relation: how to get it at this point? Where is it stored?

I used this, inside the AR relations() method:




$id = Yii::app()->request->getParam('id');



It works in general, but I do not like it because the current model ID is not always called ‘id’ in some actions (when using ajax, for example).




get_class($this);



Sorry, probably it wasn’t clear. By ID, I simply mean the primary key (normally called by GET). For example, if I send a request like model/view/id/78 I would like to get 78 inside the relations() method.

How to get this attribute of the model at that point in runtime (without relying on $_GET or similar)?

Hi este,

What do you want to do with the acquired PK?

You say you want to use it in defining MANY_MANY relation, but usually we don’t do that kind of things.

Could you show us some code about your current model and the relation?

Thanks Softark. Actually you must be right! That solution was a bit experimental and very poor in the end. I got to change a bit my tables and could get the same result without that Id.

I needed to use one single table for several MANY-MANY relations: I needed to join 6 different models in every possible way.

Finally I decided to make a single associative table with columns like artwork_id, artist_id, exhibition_id, press_id… and I set several relations as usual.

(I put this code in ActiveRecord class, that extends CActiveRecord, and is used by almost all my models…)




public function relations()

    {

	    $thisModel = strtolower(get_class($this));

	    $lang = app()->language;

	    //$id = Yii::app()->request->getParam('id'); // no needed anymore

	    

	    return array(

		

		'preview'=>array(self::BELONGS_TO,'Art','preview_id'),

		

		'arts'=>array(

			self::MANY_MANY,

			'Art',

			'relations(art_id, '.$thisModel.'_id)',

			'scopes' => array('notTrash'),

			'order' => 'sort_order'

		),

		

		'artists'=>array(

			self::MANY_MANY,

			'Artist',

			'relations(artist_id, '.$thisModel.'_id)',

			'scopes' => array('notTrash'),

			'order' => 'name_'.$lang

		),


		'expos'=>array(

			self::MANY_MANY,

			'Expo',

			'relations(expo_id, '.$thisModel.'_id)',

			'scopes' => array('notTrash'),

			'order' => 'end_date'

		),

		

		'editions'=>array(

			self::MANY_MANY,

			'Edition',

			'relations(edition_id, '.$thisModel.'_id)',

			'scopes' => array('notTrash'),

			'order' => 'year'

		),

		

		'press'=>array(

			self::MANY_MANY,

			'Press',

			'relations(press_id, '.$thisModel.'_id)',

			'scopes' => array('notTrash'),

			'order' => 'date'

		),

		

		'news'=>array(

			self::MANY_MANY,

			'News',

			'relations(news_id, '.$thisModel.'_id)',

			'scopes' => array('notTrash'),

			'order' => 'date'

		)

		

		

	    );

    }



Any comment/criticism/suggestion would be greatly appreciated. ;)

I see. I think I’ve got your intention. :)

You want a generic solution that can establish a lot of MANY_MANY relations among the items (Art, Artist, Expo, Edition, Press and News) all at once in a base class. Am I right?

Um, I wouldn’t do that.

It would make things unnecessarily complicated and fat, I guess.

How would you achieve the same goal? I guess the only alternative is creating a lot of associative tables, which is surely worse. Am I missing something? (I wouldnt be surprised…)

This way, with just one associative table, the models are very similar and I try to reuse as much code as possible (almost all models use the same controller actions and widgets).

You can easily get pages with Artist and all its related content (Artworks, Exhibitions, Editions, Press articles, News…).

What would be a better solution?

There are several things that I worry about in your design.

  1. A big fat single bridge table for 6 MANY_MANY relations doesn’t seem to be very fast or easy to maintain.

  2. Artist, for instance, would have a MANY_MANY relation named “artists” inherited from your base class. It doesn’t make sense.

I would go simple and flat, maybe with a lot of similar lines of code repeated, and with a lot of dedicated bridge tables for every MANY_MANY relations. :D

Well, I don’t have any intention to criticize your way of doing. It should be a matter of taste, and I just love KISS more than DRY. I would prefer 1,000 lines of simple and easy code more than 500 lines of complicated tricky code when I couldn’t think of an elegant solution. :)