CakePHP HABTM condition - php

I want to make a condition on my HABTM attributes
I have the following HABTM relations in CakePHP 2.x:
Practise.php
public $hasAndBelongsToMany = array(
'Attribute' => array(
'className' => 'Attribute',
'joinTable' => 'practises_attributes',
'foreignKey' => 'practise_id',
'associationForeignKey' => 'attribute_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
Attribute.php
public $hasAndBelongsToMany = array(
'Practise' => array(
'className' => 'Practise',
'joinTable' => 'practises_attributes',
'foreignKey' => 'attribute_id',
'associationForeignKey' => 'practise_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
Now I want to find all including a condition on Attributes in my PractiseController.php
PractiseController.php
$cond['Attribute.id'] = array(1,2,3);
$this->Practise->find('all', array('conditions' => $cond));
Then I get the following error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Attribute.id' in 'where clause'
SQL Query:
SELECT
Practise.id,
Practise.title,
Practise.body,
FROM db.practises AS Practise
WHERE Attribute.id IN (1, 2, 3)
How can I make CakePHP also Join the HABTM table into the find query?

You can use contain for example
$this->Practise->find('all', array('contain' => 'Attribute.id = whatever'));
You can manually join too with:
$options['joins'] = array(
array('table' => 'practises_attributes',
'alias' => 'PractiseAttribute',
'type' => 'INNER',
'conditions' => array(
'Attribute.id = whatever',
)
) );

Related

HABTM Cake php find

I have tables below with HABTM associations.
user, group , groups_users
group , project, projects_groups
public $hasAndBelongsToMany = array(
'Group' =>
array(
'className' => 'Group',
'joinTable' => 'groups_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'group_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => ''
)
);
I am trying to get all users, as a list for checkboxes, that are on a project using project id using query below
$users = $this->User->Group->Project->find('list',
array(
'conditions' => array('Project.id' => $this->Session->read('Projectid'))
,'contain' => array(
'User' => array( 'fields' => 'User.id', 'User.email')
)
)
);
But error below
Model "Project" is not associated with model "User"
I have actually tried different ways to get this working but cant seem to get it right, how can i achieve what i want. cheers
I achieved what i wanted with joins , is there a way to do this by using model associations, instead of the manual joins option?
$options['joins'] = array(
array('table' => 'groups_users',
'alias' => 'gu',
'type' => 'LEFT',
'conditions' => array(
'gu.user_id = User.id',
)
),
array('table' => 'projectGroups',
'alias' => 'pg',
'type' => 'LEFT',
'conditions' => array(
'pg.group_id = gu.group_id',
)
)
);
$this->User->recursive = -1;
$options['conditions'] = array(
'pg.project_id = ' => $this->Session->read('Projectid'),
'User.Active = ' => true
);
$users = $this->User->find('list', $options);

Cakephp Containable query with a condition AND model hasMany with also a condition

I'm here to ask a question related to the CakePhp engine.
I was just coding when I asked myself this :
I have a Customer model that hasMany Address BUT with 2 alias (one for Address.type = "l" and one for Address.type = "f")
Everything works fine, but let's suppose I want to make a special query that get me all the Customer data and the two related Address WITH a filter for each alias.
What should I do ?
Because when I'm making the query it's like the first condition (the one in the alias) is discard and the only one working is the last one.
Customer model
public $hasMany = array(
'AddressB' => array(
'className' => 'Address',
'foreignKey' => 'customer_id',
'dependent' => true,
'conditions' => array("AddressB.type" => "f"),
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'AddressD' => array(
'className' => 'Address',
'foreignKey' => 'customer_id',
'dependent' => true,
'conditions' => array("AddressD.type" => "l"),
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
And then my query : (also in the Customer model)
$d = $this->find("all", array(
"conditions" => array(
"id" => $customer_id
),
"contain" => array(
"AddressD" => array(
"conditions" => array("active" => true),
"Cp"
),
"AddressB" => array(
"conditions" => array("active" => true),
"Cp"
)
)
)
);

Using Find to return values using a condition based on a related model

I have a Company model which is related to a MonthlyReturn model. A company can have many MonthlyReturns. I am trying to get an array of all companies which have a monthly return for a specified month.
The code I am using is as follows:
$this->Company->find('all', array('contain' => array(
'MonthlyReturn' => array(
'conditions' => array('MonthlyReturn.month' => "2012-01-01")
)
)));
The Company Model:
public $hasMany = array(
'Employee' => array(
'className' => 'Employee',
'foreignKey' => 'company_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
),
'MonthlyReturn' => array(
'className' => 'MonthlyReturn',
'foreignKey' => 'company_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
public $hasOne = 'Umuser';
}
This code is returning all companies rather than those with a return for the month. The 'MonthlyReturn.month' field will always be in the format above, i.e year and month will change but will always be the 1st of the month.
Any advice would be appreciated.
your code says, that you ask for a specific date, not a month.
try this:
$this->Company->find('all', array('contain' => array(
'MonthlyReturn' => array(
'conditions' => array('MonthlyReturn.month LIKE' => "2012-01%")
))));
I'm not sure if there is a better way but you can do it in two calls like this:
$company_ids = $this->MonthlyReturn->query("SELECT DISTINCT company_id FROM monthy_returns WHERE month = '2012-01-01';")
$this->Company->find('all', array(
'conditions' => array('Company.id' => $company_ids[0]),
'contain' => array('MonthlyReturn' => array(
'conditions' => array('MonthlyReturn.month' => "2012-01-01")
)
)));
That's the idea but some debugging may be required

CakePHP SQL Error

Im trying to do a purge of records in a database though when I made my query and associations it seems to not want to do it correctly. I got the following error and Im confused as to why this is occurring:
SQL Error: 1054: Unknown column 'GuardiansStudents.student_id' in 'where clause'
The query that gets displayed afterwards is the following:
Query: SELECT `User`.`id`, `Guardian`.`id`
FROM `guardians` AS `Guardian`
LEFT JOIN `users` AS `User` ON (`Guardian`.`user_id` = `User`.`id`)
WHERE `GuardiansStudents`.`student_id` IS NULL
AND `User`.`active` = 1 AND `User`.`changeapprovalneeded` = 0
I also have the following associations in the Guardian model, not sure if Im doing this properly, and possibly this is where the error is occurring:
class Guardian extends AppModel {
var $name = 'Guardian';
//The Associations below have been created with all possible keys,
// those that are not needed can be removed
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
var $hasAndBelongsToMany = array(
'Student' => array(
'className' => 'Student',
'joinTable' => 'guardians_students',
'foreignKey' => 'guardian_id',
'associationForeignKey' => 'student_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
This is the code to do the purge function:
function manager_purgebygrade() {
ini_set('max_execution_time','120');
$this->layout = "manager";
$this->User->recursive = 0;
$grades = $this->User->Student->Grade->getDropDownList();
$this->set(compact('grades'));
//debug($this->data);
if(!empty($this->data['User']['grade_id']))
{
//$this->User->bindModel(array())
$users = $this->User->find(
'list',
array(
'fields' => array(
'User.id'
),
'conditions' => array(
'Student.grade_id' => $this->data['User']['grade_id']
),
'recursive' => 0
)
);
//debug($users);
$this->User->deleteAll(array('User.id' => $users), true);
$this->User->Guardian->bindModel(
array('hasOne' => array('GuardiansStudents')));
$guardianswithnostudents = $this->Guardian->deleteGuardiansWithNoStudent();
$guardians = $this->User->Guardian->find(
'list',
array(
'fields' => array(
'User.id',
'User.id'
),
'conditions' => array(
'GuardiansStudents.student_id' => null,
'User.active' => 1,
'User.changeapprovalneeded' => 0
),
'recursive' => 1
)
);
$this->User->deleteAll(array('User.id' => $guardians), true);
$this->set(compact('users','guardians','guardianswithnostudents'));
}
}
Hopefully someone can point me in the right direction I would greatly appreciate it :).
Your where clause:
WHERE `GuardiansStudents`.`student_id` IS NULL
is using table GuardiansStudents that appears nowhere in the from clause or join clause.
the model is GuardiansStudent, not GuardiansStudents.

Cakephp Multiple hasAndBelongsToMany HABTM

I have a table Tasks_Users with id, task_id,user_id and sender_id. Problem is user_id and sender_id are both referring to facebook_id in Users table and I'm not sure how I can hook them together with two foreign keys.
Is there a way we can get two foreign keys defined with HABTM relationship from one column?
UPDATE: Below is what I have currently set up in my Task model.
var $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'tasks_users',
'foreignKey' => 'task_id',
'associationForeignKey' => 'user_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
),
'Sender' => array(
'className' => 'User',
'joinTable' => 'tasks_users',
'foreignKey' => 'task_id',
'associationForeignKey' => 'sender_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
Below is for User model
var $hasAndBelongsToMany = array(
'Task' => array(
'className' => 'Task',
'joinTable' => 'tasks_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'task_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
Below is TasksUser model
var $belongsTo = array(
'Task' => array(
'className' => 'Task',
'foreignKey' => 'task_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Sender' => array(
'className' => 'User',
'foreignKey' => 'sender_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
I managed to get two multi-select boxes one for User_id and the other for Sender_id but the problem is I cannot save both at the same time for the same row...
The data arrays come as like this $this->data['User']['User'][] and $this->data['Sender']['Sender'][]
Theoretically it should save both but unfortunately it only saves Sender_id in the TasksUser table when you save using add action in scaffolding for Tasks controller and saves only User_id in the TasksUser table when you save using add action in scaffolding for Users controller.
The TasksUser tables are as below:
id task_id user_id sender_id
How can I make it so it saves both user_id and sender_id at the same row???
You have to put bellow code in your controller,
$this->TaskUser->bindModel(
array('belongsTo' => array(
'User1' => array(
'className' => 'User',
'foreignKey' => 'user_id'),
'User2' => array(
'className' => 'User',
'foreignKey' => 'sender_id'),
)
)
);
It should work normally, I mean without any other correction:
If you have a table User which relates via HABTM to other tables, when you make a saveAll CakePhp should automatically update the Join table. For me it does work.

Categories