tags:

views:

159

answers:

3

Hello!

I have a small problem. I am making a site that has Tags and Questions. I have a Question model, Tag model, QuestionsTag model, everything fits together nicely. The user upon asking something puts the tags in the field seperated by a space (foo bar baz) much like on stackoverflow.com.

Now, here is the code to check if a tag already exists or not and entering the tag into the database and the required associations:

    function create () {
        if (!empty($this->data)) {
            $this->data['Question']['user_id'] = 1;
            $question = $this->Question->save ($this->data);

            /**
            * Preverimo če se je vprašanje shranilo, če se je,
            * vprašanje označimo.
            */
            if ($question) {
                $tags = explode (' ', $this->data['Question']['tags']);
                foreach ($tags as $tag){
                    if (($tagId = $this->Tag->existsByName($tag)) != false) {
                        /**
                        * Značka že obstaja, torej samo povezemo trenuten
                        * id z vprašanjem
                        */
                        $this->QuestionsTag->save (array(
                            'question_id' => $this->Question->id,
                            'tag_id'      => $tagId
                        ));
                    }
                    else {
                        /**
                        * Značka še ne obstaja, jo ustvarimo!
                        */
                        $this->Tag->save (array(
                            'name' => $tag
                        ));

                        // Sedaj pa shranimo
                        $this->QuestionsTag->save(array(
                            'question_id' => $this->Question->id,
                            'tag_id'      => $this->Tag->id
                        ));
                        $this->Tag->id = false;
                    }
;               }
            }
        }
    }

The problem is this, a Question has an id of 1 and I want it to have the tags with id of 1, 2, 3.

When the 2nd and 3rd save get called, Cake sees that in the questions_tags table is already a question with id 1, so it just updates the tag.

But this is not correct, as there should be many questions in that table with the same id, as they refer to different tags belonging to them.

So, is there a way to prevent this? Prevent the save method from UPDATEing?

Thank you!

A: 

Check out saveAll. You can make a single call to $this->Question->saveAll(), and it will save any associated data you supply as well. Note that with HABTM data, it will perform a DELETE for any questions_tags associated with that question_id, then perform an INSERT for all the tag_id's included with your data.

Matt Huggins
A: 

if you want to make sure, that a new entry (INSERT) is made rather then an update, you can set $this->create(); right in front of the save call. See http://book.cakephp.org/view/75/Saving-Your-Data (in the upper part of the page): When calling save in a loop, don't forget to call create().

harpax
+2  A: 

This behavior isn't specific to HABTM relationships. You are calling the save() method inside of a loop. After the first save, an id value is set and each subsequent save call sees the id and assumes it's an update. Within a loop, you first need to call model->create() to reset an id value that may exist.

From the CakePHP Docs at http://book.cakephp.org/view/75/Saving-Your-Data:

When calling save in a loop, don't forget to call create().

In your case, it would look like this:

$this->QuestionsTag->create();
$this->QuestionsTag->save (array(
                        'question_id' => $this->Question->id,
                        'tag_id'      => $tagId
                    ));
Rob Wilkerson
That did the trick. I guess I missed that part in the manual, will have to read more carefully in the future.
vanneto