When I fetch records using hasAndBelongsToMany it sends me the following output:
[Location] => Array
(
[id] => 1
[uuid] => 5a8e4d7f-e1d0-11e4-9567-c03fd5623744
[name] => chandigarh
[address_line1] => dummy
[address_line2] => dummy
[latitude] => 30.737780
[longitude] => 76.784439
[timezone] => UTC
[is_deleted] => 0
[created] => 2015-04-13 16:59:31
[modified] => 2015-04-13
[entry_ts] => 2015-04-13 16:59:31
)
[Department] => Array
(
[0] => Array
(
[dept_name] => Heater
[LocationDepartment] => Array
(
[id] => 1
[location_id] => 1
[department_id] => 1
[is_deleted] => 0
[created] => 2015-04-13 17:00:50
[modified] => 2015-04-13 17:00:50
[entry_ts] => 2015-04-13 17:00:50
)
)
)
But I don't need the LocationDepartment array. Can any one help me?
If your using a quick find you can do this before you do it
$this->Location->recursive = 1;
$this->Location->findById($id);
If your using a full find you can add in recursive as part of the passed parameters
$this->Location->find('first', array('conditions' => array('id' => $id), 'recursive' => 1));
Posting your sample code will help solve something this simple
You can also include the 'containable' behavior on the Model which will let you specify exactly what models/data to retrieve back.
class Location extends AppModel {
var $actsAs = array('Containable');
function GetRecord($id) {
return $this->find('first', array(
'conditions' => array(
'id' => $id,
),
'contain' => array('Department'),
);
}
}
Related
I have a attributes_products and a products table, i don't know why but my data are saved twice (for the attributes_products_table). so if i go to the product page i will insert one row, i will get one data but if there is one data for example, cake will save this data twice plus the new one. Thanks
if($this->request->is('post') || $this->request->is('put') ){
$d = $this->request->data;
if($this->Product->saveall($d, array('deep' => 'true'))){
$this->Session->setFlash("Le produit a bien été enregistré","notif");
}
}
Product Model ;
public $hasMany = array(
'AttributsProduct' => array(
'className' => 'AttributsProduct',
'foreignKey' => 'product_id',
'dependent' => false
),
'ImagesProduct' => array(
'className' => 'ImagesProduct',
'foreignKey' => 'product_id',
'dependent' => false
)
);
Array
(
[Product] => Array
(
[company_id] => 18
[name] => iWatch
[category_id] => 1
[description] => iWatch
[id] => 4
[main_image_file] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
)
[AttributsProduct] => Array
(
[1] => Array
(
[attribut_id] => 2
[description] => sceen
)
[2] => Array
(
[attribut_id] => 1
[description] => monitor
)
)
)
The new generated array for the HABTM record needs to know the existent id if it already exists, or a null if it's supposed to create a new record. In any case, it should have the belongsTo id as well for both tables in the relationship.
I have Questions table which have store so many question. Question related to question_topics so have create has many relationship with question. Now it's look like this:
$this->Question->bindModel(
array(
'hasMany' => array(
'QuestionTopic'=>array(
'className' => 'QuestionTopic',
'foreignKey' => 'question_id',
'dependent' => true,
'conditions' => array('QuestionTopic.areas_id' => 165),
'type' => 'left'
)
)
)
);
print_r($this->Question->find('all'));
die;
When i saw the result then it look like this
Array
(
[0] => Array
(
[Question] => Array
(
[id] => 89
[user_id] => 1
[question_group_id] => 0
[question] => jQuery function here
[target_id] => 1
[type] => 1
[order] => 1
[description] => additional info here
[privacy_friend_id] =>
[channel_id] => 1
[status] => 0
[location] => Chandigarh, India
[regions] => 307
[select_country] => 381
[select_states] => 515
[created] => 2014-04-15 06:59:44
[modified] => 2014-04-15 06:59:44
)
[QuestionTopic] => Array
(
[0] => Array
(
[id] => 167
[areas_id] => 165
[question_id] => 89
)
)
)
[1] => Array
(
[Question] => Array
(
[id] => 90
[user_id] => 1
[question_group_id] => 0
[question] => Art
[target_id] => 2
[type] => 1
[order] => 1
[description] => addional infomation here
[privacy_friend_id] =>
[channel_id] => 1
[status] => 0
[location] => Chandigarh, India
[regions] => 307
[select_country] => 381
[select_states] => 515
[created] => 2014-04-15 07:52:17
[modified] => 2014-04-15 07:52:17
)
[QuestionTopic] => Array
(
)
)
)
I want first record only which have Question topic id 167 not second one. How can i do this.
Don't use hasMany, Use has one like this
$this->Question->bindModel(
array(
'hasOne' => array(
'QuestionTopic'=>array(
'className' => 'QuestionTopic',
'foreignKey' => 'question_id',
'dependent' => true,
'type' => 'left'
)
)
)
);
print_r($this->Question->find('all',array('conditions'=>array('QuestionTopic.areas_id' => array('165')))));
Something like this?
$question = $this->Question->find('first', array('conditions' => array('QuestionTopic.id' => 167));
I have a 2 CakePHP models, Articles and Categories, attached using a hasAndBelongsToMany relationship, like so:
$category = new Category();
$category->bindModel(array('hasAndBelongsToMany' => array(
'Article' => array(
'className' => 'Article',
'joinTable' => 'articles_categories',
'foreignKey' => 'category_id',
'associationForeignKey' => 'article_id',
'fields' => 'id,name'
))));
$this->set('categories', $category->find('all',
array(
'fields' => 'id,name'
)));
...but then, when I print out $categories, I get the following:
Array
(
[0] => Array
(
[Category] => Array
(
[id] => 31
[name] => category name
[article_count] => 1
)
[Article] => Array
(
[0] => Array
(
[id] => 1445
[name] => article name
[teaser] =>
[author_id] => 3
[ArticlesCategory] => Array
(
[id] => 6634
[article_id] => 1445
[category_id] => 31
[author_id] => 3
[created] => 2014-03-10 12:27:26
[modified] => 2014-03-10 12:27:26
)
)
)
)
I really don't need the [ArticlesCategory] member of [Article]. This just leads me back to information I already have. I tried limiting recursion but that didn't help.
How would I get rid of this?
You have two options:
[1] Reduce recursive value to 0 (CakePHP default: 1)
$category->recursive = 0;
$category->find('all',
array(
'fields' => 'id,name'
))
[2] Start using ContainableBehaviour (my own preference), which gives you more control over model data retrieved
Add following to AppModel for App-wide coverage:
public $actsAs = array('Containable');
The find method becomes:
$category->find('all',
array(
'fields' => 'id, name',
'contain' => 'Article'
))
That should do it!
To explain the issue I'm having, I'll use an example. Let's say that I'm building a system where students can sign up for one or more afterschool courses, but a school official has to approve the sign-up in order for it to be valid. So I have these models:
Course (belongs to "Teacher", hasAndBelongsToMany "Student")
Student (hasAndBelongsToMany "Course")
Teacher (hasMany "Course")
Now let's say I want to see a list of all of the unapproved sign-ups that are for ninth-graders. That's easy:
$this->request->data = $this->Student->CoursesStudent->find('all', array(
'conditions' => array(
'CoursesStudent.is_approved' => null,
'Student.grade' => 9
)
));
The thing that I'm struggling with is pulling the teacher's data as well (more than just their ID). I've tried this:
$this->request->data = $this->Student->CoursesStudent->find('all', array(
'conditions' => array(
'CoursesStudent.is_approved' => null,
'Student.grade' => 9
),
'contain' => array(
'CoursesStudent',
'Course' => array(
'Teacher' => array(
'fields' => array(
'Teacher.id',
'Teacher.name'
)
)
),
'Student'
)
));
But it doesn't have any effect whatsoever on the returned array. To make it easy for you to throw this into an existing CakePHP project to play with, here is the database schema and data and here is what you can paste into a random action of an existing CakePHP project. This is what I'm trying to get (notice that the teacher's data is there):
Array
(
[0] => Array
(
[CoursesStudent] => Array
(
[id] => 1
[course_id] => 1
[student_id] => 1
[is_approved] =>
[created] => 2012-12-11 00:00:00
[modified] => 2012-12-11 00:00:00
)
[Course] => Array
(
[id] => 1
[teacher_id] => 1
[title] => Introduction to Improvisation
[start_date] => 2012-12-17
[end_date] => 2012-12-21
[created] => 2012-12-11 00:00:00
[modified] => 2012-12-11 00:00:00
[Teacher] => Array
(
[id] => 1
[first_name] => John
[last_name] => Doe
[created] => 2012-12-11 00:00:00
[modified] => 2012-12-11 00:00:00
)
)
[Student] => Array
(
[id] => 1
[first_name] => Bill
[last_name] => Brown
[grade] => 9
[created] => 2012-12-11 00:00:00
[modified] => 2012-12-11 00:00:00
)
)
)
Thanks!
You must set $recursive to -1 before using contain() will work.
Also, make sure your model is set to use the Containable Behavior. In this case, since 'Course' is also containing something, it needs to use the Containable behavior too.
(You could think about setting the below $actsAs in your AppModel to make Containable available to every model.)
//in your CoursesStudent model (and in your Course model)
public $actsAs = array('Containable');
And here's your find, but with setting recursive first:
$this->Student->CoursesStudent->recursive = -1;
$this->request->data = $this->Student->CoursesStudent->find('all', array(
'conditions' => array(
'CoursesStudent.is_approved' => null,
'Student.grade' => 9
),
'contain' => array(
'CoursesStudent',
'Course' => array(
'Teacher' => array(
'fields' => array(
'Teacher.id',
'Teacher.name'
)
)
),
'Student'
)
));
I have the folowing associations
post->primary->secondary
$results = $this->Post->find('all', array(
'conditions' => array(
'Post.post_id =' => 2,
'Primary.secondary_id !=' => null
),
'contain' => array(
'Primary' => array(
'Secondary' => array(
'conditions' => array('Secondary.short_code =' => 'code')
)
)
)
));
Returns this.
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 2
[created] => 2012-10-29 09:48:29
[modified] => 2012-10-29 09:48:29
)
[Primary] => Array
(
[id] => 3
[secondary_id] => 6
[Secondary] => Array
(
[id] => 6
[short_code] => code
[created] => 2012-10-31 11:19:56
[modified] => 2012-10-31 11:20:03
)
)
)
However when I change
'conditions' => array('Secondary.short_code =' => 'code')
to
'conditions' => array('Secondary.short_code !=' => 'code')
it still returns the primary record, when I dont want it to.
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 2
[created] => 2012-10-29 09:48:29
[modified] => 2012-10-29 09:48:29
)
[Primary] => Array
(
[id] => 3
[secondary_id] => 6
[Secondary] => Array
(
)
)
)
It's hard to know exactly what you're hoping to achieve, but I THINK it sounds like you're trying to limit the 'Primary' results based on conditions against the 'Secondary' model.
If that's the case, you're going to need to use joins() instead of contain().
The reason: When you use CakePHP's Containable Behavior, it actually does separate queries, then combines the results before returning the data to you. Doing it this way is great in many ways, but it does not allow you to limit parent results based on conditions against it's children.
To do that, just use joins(). (CakePHP syntax which creates MySQL JOIN)