Reputation: 54949
I have a table called user_relationship. which has two foreign keys refering back to the User table to map that they are friends.
CREATE TABLE `user_relationships` (
`id` int(11) unsigned NOT NULL auto_increment,
`status` varchar(255) default 'pending',
`time` datetime default NULL,
`user_id` int(11) unsigned NOT NULL,
`friend_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_user_relationships_users1` (`user_id`),
KEY `fk_user_relationships_users2` (`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
when i try to bake it naturally doesnt understand that the friend_id has to refer to User module. i wanna manual edit the code but o have some problem understanding what parts to edit in the following
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Friend' => array(
'className' => 'Friend',
'foreignKey' => 'friend_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
In this part of the code i wanna refer the friend_id to the User Table
'Friend' => array(
'className' => 'Friend',
'foreignKey' => 'friend_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
i tried doing this.. do i need to change anything else ?
'Friend' => array(
'className' => 'Friend',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
Upvotes: 1
Views: 1677
Reputation: 129
I was able to get away with the following:
class User extends AppModel {
var $hasAndBelongsToMany = array(
'Friends1' => array(
'className' => 'User',
'joinTable' => 'friends',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
'with' => 'Friend'
),
'Friends2' => array(
'className' => 'User',
'joinTable' => 'friends',
'foreignKey' => 'friend_id',
'associationForeignKey' => 'user_id',
'with' => 'Friend'
)
);
function afterFind(array $results) {
// Merge both sides of the relationship into one alias
foreach ($results as $key=>$result) {
if (isset($result["Friends1"]) && isset($result["Friends2"])) {
$results[$key]["Friends"] = array_merge($result["Friends1"], $result["Friends2"]);
unset($results[$key]["Friends1"]);
unset($results[$key]["Friends2"]);
}
}
It's messy, but you get the idea: grab both sides of the relationship, then merge them after a database read :)
Upvotes: 1
Reputation: 521995
How about this?
class UserRelationship {
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
),
'Friend' => array(
'className' => 'User',
'foreignKey' => 'friend_id'
)
);
}
class User {
var $hasAndBelongsToMany = array(
'Friend' => array(
'className' => 'User',
'joinTable' => 'user_relationships',
'foreignKey' => 'user_id',
'associationForeignKey' => 'friend_id',
'with' => 'UserRelationship'
)
);
}
Associations can be seen from different points of view:
User <- Relationship -> User
| | |
hasMany belongsTo |
Relationship <- User (user_id) hasMany
| User (friend_id) -> Relationship
| |
HABTM HABTM
User <----------------------> User
Your "physical" layout, i.e. database schema, is User -> Relationship -> User
. Your real desired relationship is a User -> User
relationship though. Technically that translates into a User hasAndBelongsToMany User
association (also called many-to-many). Since it uses three models, a many-to-many association can be broken down into:
You don't need the hasAndBelongsToMany association, but it's what you actually want. You don't really need the Relationship model at all, since it's just a helper model to connect the two Users, but if you do want to specify its associations as well, it has two belongsTo associations.
Upvotes: 2
Reputation: 5933
Your classname for 'Friend' is wrong. Since you have no table "friends" there is no model "Friend" and you have the refer to the class "User" since they share the same table.
'Friend' => array(
'className' => 'User',
'foreignKey' => 'friend_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
Upvotes: 1