Reputation: 28783
I have three tables: Users, Profiles, and Friends.
They are connected like so:
public $name = 'User';
public $hasOne = 'Profile';
public $hasMany = array(
'Post',
'Answer'
);
public $hasAndBelongsToMany = array(
'User'=>array(
'className' => 'User',
'joinTable' => 'friends',
'foreignKey' => 'user_from',
'associationForeignKey' => 'user_to'
)
);
and the profile model is just a belongsTo user so I have not shown that, and the friends model is virtual by doing the association in the user model.
So to get a list of friends for a user. I pass the username like so in the friends controller:
public function index( $username )
{
$friends = $this->User->find('first',
array(
'conditions'=>array(
'User.username'=>$username
),
'contain'=>array(
'Profile',
'Friend'=>array(
'conditions'=>array(
'Friend.status'=>1
),
'contain'=>'Profile'
)
)
)
);
$this->set('friends', $friends);
}
Which should pull the data for the friends and there associated Profile info!
However I get this error: Model "Friend" is not associated with model "Profile" [APP/Cake/Model/Behavior/ContainableBehavior.php, line 339]
so something isn't working correctly...
Can anyone help?
I tried changing the name of he hasAndBelongsToMany to Friends in the model but that throw an error that the table wasn't unqiue... so that's not the solution either.
Tables:
**users**
id
username
password
**profiles**
id
name
user_id
**friends**
id
user_from
user_to
status
If I change the Model to become:
public $hasAndBelongsToMany = array(
'Friend'=>array(
'className' => 'Friend',
'joinTable' => 'friends',
'foreignKey' => 'user_from',
'associationForeignKey' => 'user_to'
)
);
then I get this error:
Database Error
Error: SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'Friend'
SQL Query: SELECT `Friend`.`id`, `Friend`.`user_from`, `Friend`.`user_to`, `Friend`.`created`, `Friend`.`status`, `Friend`.`id`, `Friend`.`user_from`, `Friend`.`user_to`, `Friend`.`created`, `Friend`.`status` FROM `db52704_favorr`.`friends` AS `Friend` JOIN `db52704_favorr`.`friends` AS `Friend` ON (`Friend`.`user_from` = 6 AND `Friend`.`user_to` = `Friend`.`id`)
Upvotes: 1
Views: 989
Reputation: 6767
I think you are looking for something like this:
User.php
public $hasAndBelongsToMany = array(
'Friend'=>array(
'className' => 'User',
'joinTable' => 'friends',
'foreignKey' => 'user_from',
'associationForeignKey' => 'user_to'
)
);
This will alias the User table as a Friend to itself in a habtm relationship. To keep with convention, the join table should be called friends_users
with user_id
and friend_id
keys.
Here's the result I get with a test app I made (just add your conditions):
$this->User->contain(array(
'Profile',
'Friend' => array(
'Profile',
),
));
debug($this->User->find('all', array('conditions' => array('User.id' => 1))));
array(
(int) 0 => array(
'User' => array(
'id' => '1',
'name' => 'user1'
),
'Profile' => array(
'id' => '1',
'user_id' => '1'
),
'Friend' => array(
(int) 0 => array(
'id' => '2',
'name' => 'user2',
'FriendsUser' => array(
'id' => '1',
'user_id' => '1',
'friend_id' => '2'
),
'Profile' => array(
'id' => '2',
'user_id' => '2'
)
)
)
)
)
Upvotes: 1
Reputation: 87073
Your Friend
model has no user_id
and thats why User
model can't make contact with Friend
. Try with the following:
public function index( $username )
{
$this->User->Behaviors->attach('Containable');
$friends = $this->User->find('first',
array(
'conditions'=>array(
'User.username'=>$username
),
'contain'=>array(
'Profile',
'Friend'=>array(
'conditions'=>array(
'Friend.status'=>1
)
)
)
)
);
$this->set('friends', $friends);
}
Upvotes: 1
Reputation: 7847
Models and aliases of related models should be unique. In your case the problem is:
public $name = 'User';
...
public $hasAndBelongsToMany = array(
'User'=>array(
...
If friends
is the join table name, than you could use Friend
as the alias of the friend User.
Second thing is you're trying to contain both User => Profile
and User => Friend => Profile
which is probably also problematic.
In my experience, deep contain
s can get quite inefficient. You might consider dropping the Friend's Profile
from the contain, and then extracting the friend user ids and getting the profiles separately.
Upvotes: 2