I'm trying to use Containable in CakePHP with a rather odd scenario.
- Group hasAndBelongsToMany User
- Group belongsTo User
- User hasAndBelongsToMany Group
I'm uncertain, but either I've got something wrong in my query, or I'm thinking that perhaps Containable is having a difficult time automagically determining which "User" I'm attempting to refer to in my conditions. (A department has a Department Head, thus the Group belongsTo User. A department also HABTM employees, and vice versa, thus the two HABTM links.)
From the user controller (for the view), I'm trying to get the departments (groups), and ONLY the departments, that the user belongs to.
In the User Model:
public function findDepartments($id) {
$user = $this->find('first', array(
'conditions' => array(
'User.id' => $id
),
'contain' => array(
'Group.logical_group = 0',
'Group' => array(
'User' => array('fields' => array(
'id',
'firstName',
'lastName',
'ext'
))
)
)
));
return $user;
}
This gives me an array of data with all of the information that I need. However, since I want to keep the controller skinny and the model fat, I want to eliminate the returned values that I'm getting - wherein the user is returned in the data.
Data returned:
Array
(
[User] => Array
(
[id] => 46
[username] => ytruly
[firstName] => Yours
[nickname] =>
[lastName] => Truly
[active] => 1
[created] => 2009-10-06 19:10:13
[lastlogin] => 2013-10-03 12:47:52
[deactivated] =>
[name] => Truly, Yours
)
[Group] => Array
(
[0] => Array
(
[id] => 1
[name] => Administration
[parent_id] =>
[logical_group] =>
[user_id] => 70
[GroupsUser] => Array
(
[id] => 225
[group_id] => 1
[user_id] => 46
)
[User] => Array
(
[id] => 70
[firstName] => Head
[lastName] => Honcho
[ext] => 201
)
)
[1] => Array
(
[id] => 2
[name] => Computer Services
[parent_id] => 1
[logical_group] =>
[user_id] => 182
[GroupsUser] => Array
(
[id] => 226
[group_id] => 2
[user_id] => 46
)
[User] => Array
(
[id] => 182
[firstName] => Boss
[lastName] => Man
[ext] => 202
)
)
)
)
I've tried accessing a similarly named method in the Groups model, but without any luck:
public function findDepartments($user_id){
$groups = $this->find('all', array(
'conditions' => array(
'Group.logical_group = 0'
),
'contain' => array('User.id = ' . $user_id)
));
return $groups;
}
This will remove the User array from the returned data, but it is returning every single department (group) whether the join table (groups_users) has a match or not, and simply returns an empty user array along with the data it's returning.
I know I can simply use this data from my User model's method and use the Set class to remove what I don't want, but that's rather inefficient. There's got to be a way to get the Group model to properly query what I'm looking for, right?
-- EDIT/UPDATE -- I have made some progress, but in doing so long some other benefits.
I am now calling findDepartment
from the Group model:
public function findDepartments($user_id) {
$this->recursive = -1;
$options['joins'] = array(
array(
'table' => 'groups_users',
'alias' => 'GroupsUser',
'type' => 'INNER',
'conditions' => array(
'Group.id = GroupsUser.group_id'
)
)
);
$options['conditions'] = array(
'Group.logical_group = 0',
'GroupsUser.user_id = '.$user_id
);
$depts = $this->find('all', $options);
return $depts;
}
This gets me much closer to what I was looking to get in terms of data back:
Array
(
[0] => Array
(
[Group] => Array
(
[id] => 3
[name] => Adult Services
[parent_id] =>
[logical_group] =>
[user_id] => 38
)
)
[1] => Array
(
[Group] => Array
(
[id] => 9
[name] => Youth Services
[parent_id] =>
[logical_group] =>
[user_id] => 62
)
)
)
Unfortunately, I've lost the associated belongsTo
User relationship here. I've tried adding a secondary LEFT
join in the joins
array to User
, but it didn't seem to work. I'm not sure how Containable
creates its joins for HABTM to create such a result...