Is there a shortcut for creating Unary associations in Cake?
For example, a user is a friend of another user. I'm pretty sure it's going to violate cake's conventions if I try it the hard way and code the associations myself.
Cake has HABTM:
var $hasAndBelongsToMany = array(
'User' =>
array(
'className' => 'User',
'joinTable' => 'friends',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
'unique' => true
)
);
Will this work? A user model assoc to another user model.
Update:
How do I save the data now?
$this->data["Friend"] = $request["Requester"];
$this->data["Admirer"] = $request["Requestee"];
$this->Friend->create();
$this->Friend->save($this->data);
$request["Requester"] and $request["Requestee"] both hold objects of type User.
The HABTM rel is defined in the User model
var $hasAndBelongsToMany = array(
'Friend' => array(
'className' => 'Friend',
'joinTable' => 'friends',
'foreignKey' => 'user_id',
'associationForeignKey' => 'id'
),
'Admirer'=>array(
'className'=>'Friend',
'joinTable'=>'friends',
'foreignKey' => 'friend_id',
'associationForeignKey' => 'id',
)
);
All that happens is the $data->["Friend"]'s id is stored in the id column of the friends table
Here is a solution I use in an example application
Two tables are needed, users and followers. The important fields are User->id, Follower->user_id, Follower->friend_id.
I hope this snippet helps.
<?php
class User extends AppModel {
public $useTable='users';
public $hasAndBelongsToMany=array(
'Friend'=>array(
'className'=>'User',
'joinTable'=>'followers',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
),
'Admirer'=>array(
'className'=>'User',
'joinTable'=>'followers',
'associationForeignKey' => 'friend_id',
'foreignKey' => 'user_id',
),
);
}
-teh
Bjorn,
he is asking about User habtm User...
your join table should be users_users and the relation should look like this
var $hasAndBelongsToMany = array(
'Friend' =>
array(
'className' => 'UserUser',
'joinTable' => 'users_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
'unique' => true
)
);
i think that should do the trick
In CakePHP there are several variables in your model available to do that, like $hasMany, $belongsTo and $hasAndBelongsToMany. Please read the Cookbook for further explaination.. http://book.cakephp.org/view/78/Associations-Linking-Models-Together .
In your example, I think you need HABTM.
Related
I want to delete all dependent rable record
My association
Branch Model
var $hasMany =array(
'Dealbranch' => array(
'className' => 'Dealbranch',
'foreignKey' => 'DLB_BR_ID',
'dependent' =>true
)
);
Dealbranch Model
var $belongsTo = array(
'Deal' => array(
'className' => 'Deal',
'foreignKey' => 'DL_ID',
'dependent' => true
),
'Branch' => array(
'className' => 'Branch',
'foreignKey' => 'DLB_BR_ID',
)
);
Deal Model
var $hasMany = array(
'Dealbranch' => array(
'className' => 'Dealbranch',
'foreignKey' => 'DLB_DL_ID',
)
);
In controller I have used
$this->Branch->delete($id,true);
Now here whem I am deleting branch , so dependent dealbranch deleted successfully but none of any deal record deleted
I want like : whem I am deleting branch , so all dependent dealbranch should be deleted and all dependent( depend on dealbranch) deal record should be deleted
here Deal is child of Dealbranch and Dealbranch is child of branch
Now, For one branch there are multiple record in Dealbranch, and for multiple Dealbranch there is one record in Deal
Please help me. I am using cakephp 2
All the model records that are associated with Branch can be deleted by using
$this->Branch->delete($id,true);
I think if you want to remove the deal records on deleting of branch records then your model Branch should be associated with Deal model.
Just try to add like this
Branch Model
var $hasMany =array(
'Dealbranch' => array(
'className' => 'Dealbranch',
'foreignKey' => 'DLB_BR_ID',
'dependent' =>true
),
'Deal' => array(
'className' => 'Deal',
'foreignKey' => 'your_foriegn_key',
'dependent' =>true
)
);
or you may try like this
Update:
According to your requirement here Deal is child of Dealbranch and Dealbranch is child of branch your model associations should be like this.
deal branch model should be like this.
DealBranch Model
var $belongsTo = array(
'Branch' => array(
'className' => 'Branch',
'foreignKey' => 'DLB_BR_ID',
)
);
var $hasMany = array(
'Deal' => array(
'className' => 'Deal',
'foreignKey' => 'DL_ID',
'dependent' => true
),
);
deal model should be like this.
Deal Model
var $belongsTo = array(
'Dealbranch' => array(
'className' => 'Dealbranch',
'foreignKey' => 'DLB_DL_ID',
)
);
While I know the people at cakephp do not use foreign keys in their databases and rely on the framework to take care of these details, in your case if the framework is giving you problems and you have control over the database update your foreign key constraints to CASCADE on DELETE DB operations.
The basic problem is in your data model. According to your model, any branch can be connected to zero or more deals and vice versa. Thus if you delete a branch, it does not make any sense to delete any deal, because the deal could be related to another branch. If the deal was deleted, the database integrity would be corrupted.
The setting you use is often used to model M:N relationship.1
The whole picture if your data model:
And what you really meant:
Branch model
var $hasMany =array(
'Deal' => array(
'className' => 'Deal',
'foreignKey' => <set_according_to_your_column_names>,
'dependent' =>true
)
);
Deal model
var $hasMany = array(
'Branch' => array(
'className' => 'Dealbranch',
'foreignKey' => <set_according_to_your_column_names>,
)
);
This way, you can in the controller call only:
$this->Branch->delete($id,true);
or even
$this->Branch->delete($id);
since the second parameter is true by default.
1 Example of M:N relationship is Person - Address. Anyone can use more than one address (e.g. home and work) and one address can be shared by more people (family, colleagues).
i have a model that have 2 habtm association.
my models are: 'Course', 'Teacher' and 'Student.
course hasAndBelongsToMany Teacher and hasAndBelongsToMany Student.
when i coding like this:
public $hasAndBelongsToMany = 'Student';
public $hasAndBelongsToMany = 'Teacher';
Or:
public $hasAndBelongsToMany = array(
'Student' => array(
'className' => 'Student',
'joinTable' => 'courses_students',
'foreignKey'=> 'course_id',
'associationForeignKey' => 'student_id'
),
'Teacher' => array(
'className' => 'Teacher',
'joinTable' => 'courses_teachers',
'foreignKey'=> 'course_id',
'associationForeignKey' => 'teacher_id'
)
);
i see internal error
how can i code this?
Thanks
"Cannot redeclare class Course"
says it all: you probably have a copy-and-paste-error.
You declare the class wrong in your Teacher.php (should be Teacher not Course).
Consider the following HABTM relation in CakePHP 2.2.3:
class User extends AppModel
{
public $hasAndBelongsToMany = array(
'Role' => array(
'className' => 'Role',
'joinTable' => 'roles_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'role_id',
)
);
}
This works fine, but when using an alias like VeryUniqueAlias instead of Role and changing the UsersController accordingly, the m:n relation is not persisted in the database (the data passed to save() in the controller are equivalent).
This does not work:
class User extends AppModel
{
public $hasAndBelongsToMany = array(
'VeryUniqueAlias' => array(
'className' => 'Role',
'joinTable' => 'roles_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'role_id',
)
);
}
This is awkward, since the the CakePHP docs state that it should work.
Any idea why it's not working for me? Did I miss something?
Use the 'with' key to define the name of the model for the join table. In your case:
public $hasAndBelongsToMany = array(
'VeryUniqueAlias' => array(
'className' => 'Role',
'joinTable' => 'roles_users',
'with' => 'RolesUser', // first model pluralized
'foreignKey' => 'user_id',
'associationForeignKey' => 'role_id',
)
);
I was following a tutorial about permissions instead CakePHP.
I don't understand how this model (query) works.
Can anybody explain me how this query works.. I can't find what this variable hasAndBelongsToMany exactly does.
<?php
class Group extends Appmodel {
var $name = 'Group';
var $useTable 'groups';
var $hasAndBelongsToMany = array(
'Permission' => array('className' => 'Permission',
'joinTable' => 'groups_permissions',
'foreignKey' => 'group_id',
'associationForeignKey' => 'permission_id',
'unique' => true
)
'User' => array('className' => 'User',
'joinTable' => 'groups_users',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => true
),
);
}
First of all it is not a query. it is a declaration of relation of the model to other models.
$hasAndBelongsToMany means that every record in your database is associated with many records of another table, and the many records from other table can be associated with the current record as well.
for example Book can have many authors, and an authors can have many books. so it can be related as hasAndBelongsToMany.
in your case Group has many users, and users have many groups. same for permissions.
I have in a video sharing website project these models :
class Video extends AppModel {
var $name = 'Video';
var $hasAndBelongsToMany = array(
'Tag' => array(
'className' => 'Tag',
'joinTable' => 'videos_tags',
'foreignKey' => 'video_id',
'associationForeignKey' => 'tag_id',
'unique' => true,
)
);
}
class Tag extends AppModel {
var $name = 'Tag';
var $hasAndBelongsToMany = array(
'Video' => array(
'className' => 'Video',
'joinTable' => 'videos_tags',
'foreignKey' => 'tag_id',
'associationForeignKey' => 'video_id',
'unique' => true,
)
);
}
class VideosTag extends AppModel {
var $name = 'VideosTag';
var $belongsTo = array(
'Video' => array(
'className' => 'Video',
'foreignKey' => 'video_id',
),
'Tag' => array(
'className' => 'Tag',
'foreignKey' => 'tag_id',
'conditions' => '',
'counterCache' => 'videos_tag_counter'
)
);
}
The counterCache for tags is not working. I don't know why and when I tried to add a beforeSave() callback to videosTag model I found that it doesn't execute when a video get saved (and this video has tags and i find them in the database so how the relation videosTags is saved ? ) !!! can any body explain why this is happening.
Saving a Video with data like this:
array(
'Video' => array(
...
),
'Tag' => array(
'Tag' => array(
...
),
),
);
on the Video model will not trigger a beforeSave callback on the VideosTag model because Cake handles HABTM data without requiring (or even using) the join/with/through model.
There is no built in functionality for what you are trying to achieve, as far as I am aware.
Check out Counter Cache behavior for HABTM relations, might do what you need