2

Asked before but still in the dark.

cakePHP HABTM, am I getting it all wrong?

Will try again:
I have two tables: stores and managers
I want to create a new table, managers_stores and use it to keep a complete list of mangers for each store.
I understood that each save() action that will provide the full record data (as I intend to do) will result in the deletion of the table rows and only the new record will be kept..
This is an UNDESIRED behavior for my needs. So, how should I manage the HABTM info of my application and what's the idea behind deleting data that I saved?!

thanks

Community
  • 1
  • 1
yossi
  • 3,090
  • 7
  • 45
  • 65

2 Answers2

7

save() will not delete anything, only saving with saveAll() will truncate the managers_stores entries for the particular model you're saving, if the unique value of the relationship is true. This is not made entirely clear in the manual:

unique: If true (default value) cake will first delete existing relationship records in the foreign keys table before inserting new ones, when updating a record. So existing associations need to be passed again when updating.

http://book.cakephp.org/1.3/en/view/1044/hasAndBelongsToMany-HABTM

Whenever you save() an individual record, only that individual record will be touched.
When you saveAll() a, say, Manager record with associated Store records in the same go, the managers_stores links will be reset and only the Stores that were in the record you saved will be associated with the Manager. E.g. (in pseudo code):

  • Manager HABTM stores 1, 2 and 3
  • Manager->saveAll(array('Manager' => ..., 'Store' => array(4, 5, 6)))
  • Manager now HABTM stores 4, 5 and 6; the existing associations were overwritten

So, either set the unique value in the association to false if you don't like this behavior, or manage the HABTM records manually. To be quite honest, for any halfway complex application, relying on Cake's automagic handling of HABTM relationships can get quite fragile and hard to debug, so I always manage HABTM records myself.

$this->Manager->save(...);
$this->Manager->ManagersStore->save(array('manager_id' => $this->Manager->id,
                                          'store_id'   => 42));
Community
  • 1
  • 1
deceze
  • 510,633
  • 85
  • 743
  • 889
  • thanks. i will do it that way. tho i don't really understand why it is .. what is the login behind this default behavior ? – yossi Jan 07 '12 at 23:32
  • It defaults to saving the "absolute state" of the model. You are telling it to save the Manager record, which, according to you, is associated with the stores 4, 5 and 6. Cake takes this to mean that the Manager has *only* the stores 4, 5 and 6. This makes sense for simple models with few associations that are usually managed within one interface (say, a blog post with associated tags). – deceze Jan 07 '12 at 23:35
1

'Has and Belongs to many' is where the objects are loosely tied together. If you used the stores and managers analogy, one store has many managers, and one manager has many stores (not sure how that works, maybe they are roving managers? :P).

Firstly I think the example you use with managers stores isn't HABTM. It's just one store has many managers, not many stores. Using HABTM here would imply that managers can belong to multiple stores at the same time! However I will explain anyway.

Anyhow, when using HABTM, this relationship requires an intermediate table probably called manager_stores or something similar. This would be set up automatically by CakePHP if using the automated tools. This lets you link an unlimited number of managers to an unlimited number of stores.

What happens when you update and delete records depends on the configuration of your MySQL Relationships (you need to use the InnoDB engine).

This is regardless of what relationship type you are using.

If you are using phpMyAdmin, go into the structure view of your table. Then click 'relation view'.

If you are set up with InnoDB correctly you should see the relations and two columns saying "ON UPDATE" and "ON DELETE". This determines the behavior when you modify records.

I would be here all day explaining the different types of ON DELETE and ON UPDATE actions. Try doing some research into relational database queries!

I hope this helps you a bit. I will happily answer any questions you have!

Kieran
  • 2,554
  • 3
  • 26
  • 38
  • thanks @Kieran. please note: Each manager can! manage more than one store, and each store can be managed by many managers. The third table i mentioned is the one that cake is using as the intermediate table you wrote about. My problem is that by cake's documentation - each save action to that table, will dropt, first, the content of the table and only than will save ONLY the new records.. – yossi Jan 07 '12 at 23:24
  • @yossi Oh I see what you mean. Have you tried this out yourself? Are you actually experiencing this issue or is the manual saying that? – Kieran Jan 07 '12 at 23:27