I am trying to query a hasAndBelongsToMany relationship in Cakephp 1.3, but it looks like the SQL query being run is not doing a Join on the many to many table.
I have a users table, projects table, and users_projects table. I want to get a list of all projects a user is associated with in a separate Allocations controller.
I have been reading the cakephp book on the topic: http://book.cakephp.org/view/1044/hasAndBelongsToMany-HABTM
So I have been trying this:
var_dump($this->Allocation->User->Project->find('list',array('conditions'=>array('Project.user_id'=>'21'))));
However that does not work, It returns nothing and this error:
Warning (512): SQL Error: 1054: Unknown column 'Projects.user_id' in 'where clause' [CORE/cake/libs/model/datasources/dbo_source.php, line 681]
Query: SELECT `Project`.`id`, `Project`.`name` FROM `projects` AS `Project` WHERE `Projects`.`user_id` = '21'
It looks like cakephp is not doing the required join.
This is in my projects model:
var $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'users_projects',
'foreignKey' => 'project_id',
'associationForeignKey' => 'user_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
And this is in my users model:
var $hasAndBelongsToMany = array(
'Project' => array(
'className' => 'Project',
'joinTable' => 'users_projects',
'foreignKey' => 'user_id',
'associationForeignKey' => 'project_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
So, what is the correct syntax to get the list of projects for a given user on a many to many relationship in cakephp?
Perhaps that's because you didn't make the two table names connected in alphabetical order.users_projects should be projects_users.
You are getting this error because you are using the find type 'list'. Cake's default behaviour is to select the ID and NAME fields when using this find type.
Change your find type to 'all' to retrieve the results you are expecting:
var_dump($this->Allocation->User->Project->find('list',array('conditions'=>array('Project.user_id'=>'21'))));
Related
I have the problem in Cakephp that when I define
public $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'groups_users',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
'conditions' => 'User.active=1',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
with the conditions field set, so that only users that are active are fetched from the DB, that I get the error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'User.active' in 'where clause'
for the SQL Query:
SELECT `GroupsUser`.`user_id` FROM `groups_users` AS `GroupsUser` WHERE `GroupsUser`.`group_id` = 123 AND `User`.`active`=1
Because obviously it only fetches the results from the join table. So I found here: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm in the description for conditions.
conditions: an array of find() compatible conditions or SQL string. If
you have conditions on an associated table, you should use a ‘with’
model, and define the necessary belongsTo associations on it.
What is a 'with' model and how would I implement it?
Thanks a lot in advance!
Although this question is quite old I've recently encountered the same problem and wanted to document my solution. In the above example instead of referencing the User I've had to do a simple sub query to get the associated field like this:
public $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'groups_users',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
//'conditions' => 'User.active=1',
'conditions' => array('(SELECT active FROM users WHERE users.id = GroupsUser.user_id)'=>1),
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
In my similar example finds & saves now work.
I have a Goal model that HasAndBelongsToMany Users. This HABTM is named Participant. When I try to find all the Participants of a goal, the join table for this HABTM is not being used. Here is the related code in the goal model.
class Goal extends AppModel {
var $hasAndBelongsToMany = array(
'Participant' => array(
'className' => 'User',
'joinTable' => 'goal_participants',
'foreignKey' => 'goal_id',
'associationForeignKey' => 'user_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
));
function getParticipantIDs($goalID) {
$this->bindModel(array('hasOne' => array('Participant')));
return $this->find('list', array(
'fields' => array('Participant.user_id'),
'conditions' => array('Participant.goal_id' => $goalID)
));
}
}
I am binding the Participant as hasOne so that it will create a join in the query, but I get the following error:
Warning (512): SQL Error: 1054: Unknown column 'Participant.user_id' in 'field list' [CORE\cake\libs\model\datasources\dbo_source.php, line 525]
Query: SELECT `Participant`.`id`, `Participant`.`user_id` FROM `users` AS `Participant` WHERE `Participant`.`goal_id` = '19' AND `Participant`.`status` != 2
I edited the answer after OP's comment.
If i understand well what you intend to do, this piece of code might help :
function getParticipantIDs($goalID) {
$participants = $this->GoalParticipant->find('list', array(
'fields' => array('user_id'),
'conditions' => array('goal_id' => $goalID)
));
return array_values($participants);
}
I'm not 100% sure GoalParticipant is the correct syntax. I'm pretty sure that if the join table was named goals_participants, the correct syntax would be GoalsParticipant but as it's named goal_participants I guess it might be GoalParticipant.
I would like to use hasMany through relationship to connect two users through a model invitations
I currently have the following controller:
class User extends AppModel {
var $name = 'User';
var $displayField = 'username';
var $hasMany = array(
'Invitation' => array(
'className' => 'Invitation',
'foreignKey' => 'sender_user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'Invitation' => array(
'className' => 'Invitation',
'foreignKey' => 'receiver_user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
)
}
However, when i get error:
Error: Database table sender_users for model SenderUser was not found.
Which is a bit annoying, because I already thought I specified that I want to use Invitation.
What is the issue, what code do I change?
First: you can't create the same association twice. Even from a PHP syntax perspective that's not possible. You'll have to give each association a unique name:
public $hasMany = array(
'SentInvitation' => array(...),
'ReceivedInvitation' => array(...)
);
Second, the problem is probably that you don't have an Invitation model. Cake creates a model on-the-fly according to naming conventions. Since you have a column sender_user_id, according to naming conventions you should therefore also have a sender_users table. Create the Invitation model and set it up without that association, then Cake shouldn't be looking for it.
I am trying to retrieve data from a simple table and populate a select field form.
There are two tables, Acronyms and Topics.
Currently I have:
In my acronyms_controller (method add()):
$topics = $this->Acronym->Topic->find('list');
$this->set(compact('topics'));
In my acronym (model):
var $belongsTo = array(
'Topic' => array(
'className' => 'Topic',
'foreignKey' => 'topic_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
In my Topic model:
var $hasMany = array(
'Acronym' => array(
'className' => 'Acronym',
'foreignKey' => 'topic_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
in my Acronym add view:
<?php echo $this->Form->input('topic_id'); ?>
I do not know why this is not working (it is not retrieving the Topic data in the select field). I download a simple application and did the same exercise and it did very well. I do not know what I am missing.
I would appreciate if I have your help.
Your code all appears to be correct. If the topic name is not appearing in the select field, then it is probably because the field in the database table is not correct.
For Cake to automagically popular the select with a list of Topic names, there must be a field in your Topictable called name.
Otherwise, there must be something else in your controller conflicting with this, but I'd need to see the entire add() method to determine this.
I am using CakePHP framework to build a web application. The simplest form of my problem is this:
I have a users table and a messages table with corresponding models. Messages are sent from a user to another user. So messages table has columns from_id and to_id in it, both referencing to id of users. I am able to link Message model to User model by using $belongsTo but I am unable to link User model with Message model (in reverse direction) by using $hasMany in the same manner.
var $hasMany = array(
'From' => array(
'className' => 'Message',
'foreignKey' => 'from_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'To' => array(
'className' => 'Message',
'foreignKey' => 'to_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
What can do here? Any ideas? Thanks for any help.
You can link the two models with 'hasMany' or 'belongsTo' more than one time with diffirent foreign keys at the same time.Since I don't find any example from the cookbook I tested that with a tiny piece of code and it worked as expected .