CakePHP - Conditional behaviour not working in find() - cakephp

I have SubjectGroup, which hasMany Subject.
class SubjectGroup extends AppModel {
public $hasMany = array(
'Subject' => array('order' => 'Subject.name')
);
}
class Subject extends AppModel {
public $belongsTo = array('SubjectGroup');
}
I want to get all SubjectGroups, and recursively retrieve their Subjects, but only the Subjects that have a status of 2.
$this->SubjectGroup->find('all', array(
'contain' => 'Subject.status != 2',
'order' => 'SubjectGroup.name'
));
There are no errors, but it just returns all Subjects, even the ones with status = 2.

I think you need to set the condition for the Subjects more explicitly.
$this->SubjectGroup->find(
'all',
array(
'contain' => array(
'Subject' => array(
'conditions' => array('NOT' => array('Subject.status' => 2)),
),
),
'order' => 'SubjectGroup.name'
)
);

Well, I finally discovered two problems. I was trying to add an $actsAs definition to the controller, to bring in the behaviour. I completely forgot it's not the model. You have to bring in the behaviour in the controller action.
class SubjectGroupsController extends AppController {
public function index() {
$this->SubjectGroup->Behaviors->attach('Containable');
$subjectGroups = $this->SubjectGroup->find('all', array(
'contain' => 'Subject.status != 2',
'order' => 'SubjectGroup.name'
));
}
}
But anyway, the condition only seems to work if I use the very basic syntax of:
'contain' => 'Subject.status != 2'
Anything more complex doesn't seem to work for me:
// DOES NOT WORK
'contain' => array(
'Subject' => array(
'conditions' => array('NOT' => array('Subject.status' => 2)),
),
)

Related

Cakephp 2.x where clause on multi level

Here's my models
MODEL USERLIST
class UserList extends AppModel {
public $belongsTo = array(
'UserOwner' => array(
'className' => 'Usermgmt.User',
'foreignKey' => 'owner_id'
),
'UserMember' => array(
'className' => 'Usermgmt.User',
'foreignKey' => 'member_id'
)
);
public $recursive = -1;
public $actsAs = array('Containable');
MODEL USER
class User extends UserMgmtAppModel {
public $actsAs = array('Containable');
/**
* This model belongs to following models
*
* #var array
*/
var $belongsTo = array('Usermgmt.UserGroup');
/**
* This model has following models
*
* #var array
*/
var $hasMany = array(
'LoginToken' => array('className' => 'Usermgmt.LoginToken', 'limit' => 1),
'UserListOwner' => array('className' => 'UserList', 'foreignKey' => 'owner_id'),
'UserListMember' => array('className' => 'UserList', 'foreignKey' => 'member_id'),
);
var $hasOne = array(
'PhoneNumber' => array('className' => 'PhoneNumber', 'foreignKey' => 'user_id')
);
MODEL PHONENUMBER
class PhoneNumber extends AppModel {
public $belongsTo = array(
'User' => array(
'className' => 'Usermgmt.User'
)
);
I want to do a database request on multiple parameters who are on multiple levels. This is my request.
$this->UserList->find("all", array('conditions' => array(
"UserList.type" => 1,
'UserList.owner_id' => $this->UserAuth->getUserId(),
"UserMember.PhoneNumber.phoneNumber LIKE" => "%" . "514" . "%"
), 'fields'=>array('UserMember.first_name', 'UserMember.last_name', "PhoneNumber.phoneNumber")))
My problem is when I run this request, I always receive an SQL error message who says that the field UserMember.PhoneNumber.phoneNumber does not exists.
I can do that request using standard SQL but i'dd like to do it with CakePhp.
How can I do it?
thanks
Your column name is wrong, this line "UserMember.PhoneNumber.phoneNumber LIKE" => "%" . "514" . "%" should be "PhoneNumber.phoneNumber LIKE" => "%" . "514" . "%" from the looks of things like you have in your fields.
You might also need to specify which models you want to contain like this:-
$this->UserList->find(
'all',
array(
'contain' => array(
'UserMember' => array('PhoneNumber')
),
'conditions' => array(
'UserList.type' => 1,
'UserList.owner_id' => $this->UserAuth->getUserId(),
'PhoneNumber.phoneNumber LIKE' => '%' . '514' . '%'
),
'fields'=>array(
'UserMember.first_name',
'UserMember.last_name',
'PhoneNumber.phoneNumber'
)
)
);

Cakephp Find conditions on related table with hasAndBelongsToMany

I have the following code that gives an error from the moment I do a find condition on the associated Model (HABTM):
class Users extends Model{
public $useTable = 'users';
public $hasAndBelongsToMany = array(
'UserCategories' => array(
'className' => 'UserCategories',
'joinTable' => 'user_categories_link',
'foreignKey' => 'user_id',
'associationForeignKey' => 'category_id',
'unique' => false,
)
);
public function getData($page = 0, $category = '', $subcategory = ''){
return $this->find('all', array(
'limit' => 6,
'page' => $page,
'conditions'=> array(
'active'=> 1,
'UserCategories.category_name' => $category, // THIS GIVES ERROR
'UserCategories.category_subcategory' => $subcategory, // THIS GIVES ERROR
)
));
}
In my Controller:
$this->Users->getData(0, 'somemaincategory', 'somesubcategory');
I can't seem to do conditions on the related HABTM-Model (UserCategories in this case). I also tried to use 'contain' (with $actsAs), but then he stills gives me all the User data even if there is no Category linked with it. The Category array is in that case just blank.
Hope someone can help me.
Thanks in advance,
AƤron
Do a manual join. You can use this to do an actual inner join (contain will act as a left join). http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
$this->find('all',
array(
'conditions' => array(
'active' => 1,
),
'joins' => array(
array(
'table' => 'user_categories_link',
'alias' => 'UserCategoriesLink',
'type' => 'inner',
'conditions' => array(
'UserCategoriesLink.user_id = User.id'
),
),
array(
'table' => 'user_categories',
'alias' => 'UserCategories',
'type' => 'inner',
'conditions' => array(
'UserCategories.id = UserCategoriesLink.category_id',
'UserCategories.category_name' => $category,
'UserCategories.category_subcategory' => $subcategory,
),
)
),
)
);

Cakephp HABTM issue retrieving multilevel data

I am creating an assessment database and using cakephp for the first time. I have gotten all the data entry and editing sorted but am having trouble retrieving some crucial data from a deep association:
The essence is
Course HABTM Units (table courses_units)
Unit hasMany Artefacts
Artefact hasOne AdminArtefact
Artefact belongsTo an Unit
The AdminArtefact model is used for each years dynamic data for an artefact (due_date, late_date and so on).
My problem is when I want to get all the due dates of artefacts for a particular course (which we need to check for hand in congestion)
If I do a findAll in the Artefacts controller with recursion set to '2' it gets all the data I need...but it overloads the page due to the amount of data returned. So I want to set the conditions for the findAll for the specific fields I need. However I cannot set the course in the query - From my understanding the course data is pulled from a 'separate' query as it appears in the results like this:
[Course] => Array
(
[0] => Array
(
[id] => 2
[course_code] => C0767S
[course_name] => BSc (hons) Entertainment Technology
[course_local_code] => ET
[course_leader] => 6
[colour] =>
[CoursesUnit] => Array
so as part of the query, I cannot set the course equal to a specific one, which I need to do so I can also specify the other data elements I want to pull and not the wealth of other data.
Ive tried loading the Unit model and changing the bind to a belongsTo instead of HABTM to the courses_units table but got the same dataset back again.
Ive tried going 'higher up the chain' to the CourseUnits controller and doing a '$uses' and specified all the relevant tables I want to pull data from but that didn't get anything useful.
Reading up on HABTM it doesn't automatically pull the data so I looked at joining the tables, but couldn't really see which model to make the join to get it to work.
I need to put this to bed now so hence I am asking the question: What is the most elegant way to get the due dates for all the artefacts for a specific course? (I need the course, the unit, the artefact and the due date...so something from all the tables)
QUERY String I want to use in Artefacts controller:
$data = $this->Artefact->find('all', array(
'fields' => array('Artefact.reference', 'AdminArtefact.due_date', 'ArtefactUnit.short_code', 'Course.course_code' )));
This gives the error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Course.course_code' in 'field list'
Thanks in advance!
Kevin
All relevant models:
class Course extends AppModel {
public $displayField = 'course_name';
public $hasAndBelongsToMany = array(
'Unit' =>
array(
'className' => 'Unit',
'joinTable' => 'courses_units',
'foreignKey' => 'course_id',
'associationForeignKey' => 'unit_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => 'CoursesUnit'
)
);
public $belongsTo = array(
'CourseLeader' => array(
'className' => 'User',
'foreignKey' => 'course_leader'
)
);
class Unit extends AppModel {
public $displayField = 'short_code';
public $hasMany = array(
'UnitArtefacts' => array(
'className' => 'Artefacts',
'foreignKey' => 'unit_id'
));
public $hasAndBelongsToMany = array(
'Course' =>
array(
'className' => 'Course',
'joinTable' => 'courses_units',
'foreignKey' => 'unit_id',
'associationForeignKey' => 'course_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'with' => 'CoursesUnit'
)
);
public $belongsTo = array(
'External' => array(
'className' => 'User',
'foreignKey' => 'external_examiner'
),
'Coordinator' => array(
'className' => 'User',
'foreignKey' => 'coordinator'
),
'UnitLevel' => array(
'className' => 'Level',
'foreignKey' => 'level_id'
)
);
class Artefact extends AppModel {
public $displayField = 'reference';
public $hasOne = array(
'AdminArtefact' => array(
'className' => 'AdminArtefact',
'foreignKey' => 'artefact_id'
)
);
public $belongsTo = array(
'ArtefactUnit' => array(
'className' => 'Unit',
'foreignKey' => 'unit_id'
)
);
actually setting
'recursive' => 3,
should work.

Cakephp how to set limit to assocation model?

How can I set limit to association model ("Comment" model in below code) when using paginator component.
I am using below code but not working :
$this->Paginator->settings = array(
'Post' => array(
'recursive' => 1,
'conditions' => $conditions,
'limit' => 10,
),
'Comment' => array(
'limit' => 1
)
);
You should use Containable behavior (in Post model):
public $actsAs = array('Containable');
Then, your Paginator settings should look like:
$this->Paginator->settings = array(
'contain' => array(
'Comment' => array(
'limit' => 1
)
),
'conditions' => $conditions,
'limit' => 10,
);
You have Post hasMany Comment?
If yes, You can set limit by variable $hasMany in Post model:
class Post extends AppModel {
public $hasMany = array(
'Comment' => array(
'className' => 'Comment',
//...
'limit' => '1'));
}

CakePHP multilevel models

I've been trying to figure out how to save multi-level models in CakePHP for some time now, but can't seem to find a solution.
I have three models. Survey, Question, and Choice.
Survey hasMany Question - so Question belongsTo Survey
Question hasMany Choice - so Choice belongsTo Question
The Question is linked to the Survey through its survey_id key.
The Choice, on the otherhand, is linked to the Question through its question_id key. (not directly linked to Survey though)
The form is created through $this->Form->create('Survey').
I want the application to save a survey with its corresponding questions, AND each question having their corresponding choice(s).
The problem is, only the Survey and Question models are saved. Choice gets discarded.
I'm using $this->saveAssociated($this->request->data, array( 'deep' => true) )
I will be updating my post to show the $_POST data.
Thanks,
XTN
Before saving data, you have to ensure that data should be in this format
in your controller:
$data = array('Survey' => array('id' => 1,'name' => 'test'),
'Question' => array(
array('id' => 1,'question' => 'test1','survey_id' => 1,
'Choice' => array(
array('id' => 1,'question_id' => 1,'choice' => 1),
array('id' => 2,'question_id' => 1,'choice' => 2)
)
),
array('id' => 2,'question' => 'question2','survey_id' => 1,
'Choice' => array(
array('id' => 3,'question_id' => 2,'choice' => 'sd'),
array('id' => 4,'question_id' => 2,'choice' => 'we')
)
)
)
);
$this->Survey->create();
$this->Survey->saveAssociated($data,array('deep'=>true));
Survey Model :
public $hasMany = array(
'Question' => array(
'className' => 'Question',
'foreignKey' => 'survey_id',
'dependent' => false,
)
);
Question Model :
public $belongsTo = array(
'Survey' => array(
'className' => 'Survey',
'foreignKey' => 'survey_id',
)
);
public $hasMany = array(
'Choice' => array(
'className' => 'Choice',
'foreignKey' => 'question_id',
'dependent' => false,
)
);
Choice Model :
public $belongsTo = array(
'Question' => array(
'className' => 'Question',
'foreignKey' => 'question_id',
)
);
I think it will work if found any problem please notify
Your models should looks like:
Survey Model: Survey.php
class Survey extends AppModel {
public $name = 'Survey';
public $hasMany = array('Questions' => array(
'className' => 'Question',
'foreignKey' => 'survey_id'
)
);
}
Question Model: Question.php
class Question extends AppModel{
public $name = 'Question';
public $belongsTo = array(
'Survey' => array('className' => 'Survey', 'foreignKey' => 'survey_id'),
'Answer' => array('className' => 'Choice', 'foreignKey' => 'answer_id'));
public $hasMany = array('Choices' => array('className' => 'Choice',
'foreignKey' => 'question_id'));
}
Choice Model: Choice.php
class Choice extends AppModel
{
public $name = 'Choice';
public $belongsTo = array('Question' => array('className' => 'Question',
'foreignKey' => 'question_id'));
}
Kindly ask if it not worked for you.

Resources