My data structure is as follows:
Company hasMany Regions
Region hasMany Markets
Market hasMany Stores
Store hasMany Employees
I also have the appropriate belongsTo where necessary.
I used foreign keys for associations. For example, each store has market_id.
When I delete a Company record, the correct Region is also deleted. However, it occurred to me that I also need all associated Markets, Stores, and Employees to be deleted. Or if I deleted a Market, I would need all Stores and Employees deleted.
What is the most appropriate manner of accomplishing this?
Would I add additional foreign keys to the tables? For example, would Stores need region_id and company_id in addition to market_id?
Use dependent association:
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany
dependent: When dependent is set to true, recursive model deletion is
possible. In this example, Comment records will be deleted when their
associated User record has been deleted.
You don't need to add the additional foreign keys.
Related
Cake newb here.
I have two tables. Users and Events. An user can subscribe to Multiple events.
What is the best way to implement this?
Do I have to create another table and link them or is there any other better approach.
If I do create a new table, how do i link them in cake model?
As said by jQuery.PHP.Magento.com you should use HABTM relationship but the name of the third table should be events_users because the table names should be in alphabetical order.
From the doc:
Table names are in alphabetical order by convention. It is possible to
define a custom table name in association definition.
You should use HABTM relationship.
Reason
See users will subscribe to Multiple events and
One event have multiple users subscribed for.
So this is two way relationship. Therefore you need following tables
users : To store user's data,
events : To store user's data,
events_users : To store Which user joined Which event and Vice versa(Events with n number of users)
So users_events will have 2 fields user_id , event_id , both are foreign keys and here you dont need primary key in HABTM relationship.
I have two Models, departments and users. Departments is associated by hasMany with users and users belongsTo a department. Below is the snapshots of two table structures.
department_id is foreign key in user table.When i delete the department ,the respective department_id in user table not getting deleted.it stays as assigned before.How can i delete the department_id in users table.
Actually, cakephp does not provide a mean to do that. You need to set SET NULL ON DELETE in the database.
I have two models: Store and Review. Users of my site can leave a review on a store. In my database, I have a join table, reviews_stores that associates a review with a store.
How do I link my models? I assume a Store should haveMany Review, and a Review should belong to a Store, but the join table is causing issues with CakePHP as CakePHP is assuming my reviews table has a column called store_id.
The reason I'm using a join table is because many parts of my site can be reviewed. For example, brands. A new Review record will be created and a record will be inserted into a brands_reviews table to associate the two records.
Any help would be much appreciated.
Why are you not simply using one Review model and a reviews table with a field "foreign_key" and another field "model"? By this you do not need to duplicate tables and inherit or duplicate models. This will also remove the need for a join table.
If you want to continue to use your db design then you'll have to use a HABTM association over the hasMany association. But even in the case you want to keep that jointable, again, you can use the foreign_key/model and simply have one join table and one reviews table.
By the way, your join table review_store does not follow the conventions, it should be reviews_stores. But then it differs to the schema you've used for brands_reviews. ;)
Seems to me it isn't a many-many relationship but a grouped 1-many relationship. Id lose the join tables and simply have an extra table outlining which 'group' the review belongs to. So the review table would have review_id, link_id(the foreign key for the relevant brand or store), review_type_id(foreign key depicting whether the review is for a brand or store and so on). Then the review_type table only needs to have review_type_id, review_type(varchar).
There's no need for all the join tables for each model you can review, simple store the model name itself in a field in the Review table.
Setup your relationship like so:
class Store extends AppModel {
public $hasMany = array(
'Review' => array('conditions' => array('Review.model' => 'Store')
);
}
You can then do this with as many extra models as you like without having to touch the database.
I was wondering if this is possible to do with a has many through
contents orgs folders
id id id
name name title
link
join table - folder_elements
id
element_id
order
contents has many folders through folder_elements
orgs has many folders through folder_elements
So my question is, is it possible to use element_id to store the content.id or the org.id ?
Alex
What you're describing is a sort of HABTM (HasAndBelongsToMany) association. You could define the inter-model associations as you suggest, but there's a pretty significant design flaw: how would you account for a situation where the same ID is used for an orgs record and a contents record, and wish to associate them with the same folder record? It would be impossible to differentiate between the two in your joining table.
There are a number of ways to work around this, but they require more program logic or a more disorganised database schema that presents challenges in maintainability.
The more elegant, robust solution is to rationalise your database structure. If there's no pressing need to have One Join Table to Rule Them All, you could design your model associations like this:
Content hasMany ContentsFolder belongsTo Folder
Folder hasMany ContentsFolder belongsTo Content
Org hasMany OrgsFolder belongsTo Folder
Folder hasMany OrgsFolder belongsTo Org
This is the internal structure of a HABTM association defined explicitly so you can define fields in the joining table. Your contents and folders tables would remain the same, but your two joining tables would look like:
contents_folders
-> id
-> content_id
-> order
orgs_folders
-> id
-> org_id
-> order
Unfortunately, yes, this would require defining five models instead of three, but such are the limitations of CakePHP's object-relational modelling.
Given :
Group hasMany Persons
but the relationship is independent (ie. Persons can exist without belonging to a Group), should the foreign key in the persons' table (ie group_id) be set to 0 (or NULL) when deleting a group? If you do not, the person will try to belong to a group that doesn't exist.
The reason I ask is that this is the default behavior in Cakephp. If you set dependent to true, it will delete the associated models, but if it's set to false it will leave the associated model untouched.
Yes, the foreign keys should be set to NULL (or 0, if this is your chosen 'no group' value) or you lose referential integrity. If your database supports it, you should be able to set an 'On delete' trigger or a cascade rule in your framework to enforce this. And the behaviour in CakePHP seems correct. If the value is dependent, then it should be removed on deletion. If it isn't dependent then you need to give extra behaviour logic as to the correct action to take (in this case, you want to set all values to NULL. In other cases, you may want to set to a 'default' group, etc)
In a word, yes. Leaving the foreign key on the persons table would result in the loss of referential integrity within the database.
> If you do not, the person will try to belong to a group that does't exist.
There is also a worse scenario: in the future a new group B may appear that will reuse the id of deleted group A. Then all former A group's users will be "magically" enlisted into new group B.
An alternative, more stable way to implement a situation where both entities are independent would be to remove the foreign key entirely from Person and create a join table group_persons. This way you won't have to worry about your reference integrity when deleting a group. When you delete a group, the association would be deleted from group_persons.
The table would look like this
id, group_id, person_id
The group_persons model will look like this
Person hasMany GroupPerson
Group hasMany GroupPerson
GroupPerson belongsTo Person, Group
If you want the Person to only be able to be in one group at a time, set a unique validation rule in GroupPerson.
var $validate=array(
'person_id'=>array(
array(
'rule'=>'isUnique',
'message'=>'This person is already in a group.'
)
)
);