RosSoft

Working with HABTM associations August 23, 2006

I’ve done some functions for working with HABTM associations.For example:You’ve the model Post and the model Tag. Post HABTM Tag.You want to add the Tag with id 12 to the Post with id 3. Then you can do it easy with$this->Post->addAssoc(3,’Tag’,12);

Now you want to delete the association between the Post 3 and the Tag 15? $this->Post->deleteAssoc(3,’Tag’,15);

You can even add more than one tag at once:$this->Post->addAssoc(3,’Tag’,array(11,12));

Put these functions in your AppModel: /** * Adds to a HABTM association some instances * * @param integer $id The id of the record in this model * @param mixed $assoc_name The name of the HABTM association * @param mixed $assoc_id The associated id or an array of id’s to be added * @return boolean Success */ function addAssoc($id,$assoc_name,$assoc_id) { $data=$this->_auxAssoc($id,$assoc_name); if (!is_array($assoc_id)) $assoc_id=array($assoc_id); $data[$assoc_name][$assoc_name]=am($data[$assoc_name][$assoc_name],$assoc_id); return $this->save($data); }

/** * Returns the data associated with a HABTM in an array * suitable for save without deleting the current relationships * * @param integer $id The id of the record in this model * @param mixed $assoc_name The name of the HABTM association * @return array Data array with current HABTM association intact */ function _auxAssoc($id,$assoc_name) { //disable query cache $back_cache=$this->cacheQueries; $this->cacheQueries=false;

Like this:

Related

Thanks for sharing this tool. I can see how this could be very useful in certain scenarios.

I’m glad to see you writing on this topic in particular (HABTM); it seems that many people have had a difficult time getting up to speed on the hasAndBelongsToMany association. I think it is underdocumented.

I’ve rewritten the unbindModel function to something simpler. As I usually dont have two associations with the same name I hate to provide the relationship type every time. So this function just takes a string or array of model name(s) that will be considered with the next find operation. All others will be ignored.

Freakin’ awesome, but I had to make the following modification to the last line of addAssoc() to turn off validation. This is probably just specific to my implementation, but perhaps others can benefit:

First: when copying and pasting from the site I get the wrong quotes and have to change them in the text editor. No biggie.

Second: This gives problems if you use other associations besides HABTM. I have one model that belongs_to User and habtm User, and had to alter the loop in _auxAssoc to check for numeric keys or I got extra assoc’s added:

This is awesome, and I’m grateful for it. One suggestion: why not merge both addAssoc() and deleteAssoc() into one function with an additional argument, something like this:

updateAssoc($id, ‘Tag’, array(id’s to save), array(id’s to delete))

I will do this for my project. Perhaps it’s just due to quirks of my implementation, but I find myself calling both functions back-to-back in many cases. This would permit a single save() call to the DB, rather than a call to remove some items followed by a call to add items.

I add this function to my code – hope someone finds it useful. I use this for multiple select’s, where I had to both add all selected values and delete all unselected values. I just took the logic from the add/delete functions and combined them, but there’s only 1 query and 1 save() call. This reduces the number of calls to the DB by about 1/2. It also will only save each association once (I was seeing attempts to save duplicate entries in the join table. DB won’t allow it, but why waste the effort?).