cakephp model chaining and retrieving results from multiple models - cakephp

I am in process of chaining multiple models. The goal is to retrieve the category for the keyword when I pass a keyword.
Models
Keyword
columns:
id
keyword
KeywordCategory
columns:
keyword_id
category_id
Category
columns:
id
category
The following are the association definitions that I made.
Keyword
var $hasMany = array(
'KeywordCategory' => array(
'className' => 'KeywordCategory',
'foreignKey' => 'keyword_id',
'dependent' => true
)
);
KeywordCategory
var $belongsTo = array(
'Keyword' => array(
'className' => 'Keyword',
'foreignKey' => 'keyword_id',
'dependent' => true
),
'Category' => array(
'className' => 'Category',
'foreignKey' => 'category_id',
'dependent' => true
)
);
Category:
var $hasMany = array(
'KeywordCategory' => array(
'className' => 'KeywordCategory',
'foreignKey' => 'category_id',
'dependent' => true
)
);
My question is when I currently retrieve the Keyword category currently it will return something like following:
Array
(
[Keyword] => Array
(
[id] => 2
[keyword] => rc
[modified] =>
[created] =>
)
[KeywordCategory] => Array
(
[0] => Array
(
[keyword_id] => 2
[category_id] => 2
)
[1] => Array
(
[keyword_id] => 2
[category_id] => 1
)
)
)
I want to also return the Categories signified by category_id in the result. Can anyone suggest the change that I need to make?
Thank you

Related

HABTM with join Cakephp

hello I have a table name University_Industry. It has uni_id and ind_id as foriegn keys of University table and Industry table. So meaning university will have many industries and industries will have many universities. I am getting the result successfully by running this query
public function getAllUniv(){
return $this->find('all', array(
'order' => 'uni_id',
));
}
This query returns me universities and their industries.Result look like this
Array
(
[0] => Array
(
[University] => Array
(
[uni_id] => 1
[uni_name] => NYC
)
[Industry] => Array
(
[0] => Array
(
[ind_id] => 1
[ind_name] => Finance
[UniversityIndustry] => Array
(
[id] => 1
[uni_id] => 1
[ind_id] => 1
)
)
[1] => Array
(
[ind_id] => 2
[ind_name] => Accounting
[UniversityIndustry] => Array
(
[id] => 2
[uni_id] => 1
[ind_id] => 2
)
)
)
)
Now I have another table which called users which has uni_id also as a foreign key. So I am looking for a query which can fetch only those universities with the industries which are found in users table. So It should fetch only those universities whose uni_id is exist in users table
I have no idea how can I join users table in my query and get the results.
This is how my University Modal look like at the moment
class University extends AppModel
{
public $useTable = 'university';
public $primaryKey = 'uni_id';
public $hasAndBelongsToMany = array(
'Industry' =>
array(
'className' => 'Industry',
'joinTable' => 'university_industry',
'foreignKey' => 'uni_id',
'associationForeignKey' => 'ind_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
),
);
public function getAllUniv(){
return $this->find('all', array(
'order' => 'uni_id',
));
}
}
You can join data in your find query.
$this->find('all', array(
'order' => 'uni_id',
'joins' => array(
array(
'table' => 'users ',
'alias' => 'UserJoin',
'type' => 'inner',
'conditions' => array(
'UserJoin.uni_id = University.id'
)
),
));
Here is official doc. Hope it will help you

Saving data with 2 HABTM and one hasMany association

I am trying to save data with multiple HABTM & hasMany relation. Even if I use
$this->Project->save();
$this->Project->saveMany();
$this->Project->saveAssociated();
$this->Project->saveAlll();
It does not save associated model, I can't figure out what I am doing wrong.
Models Reations
Project hasAndBelongsToMany Skill
Project hasMany Milestone
Project hasAndBelongsToMany Attachment (because Milestone's will also have attachement so can not bind project & attachment in hasMany Relation)
Project Model
class Project extends AppModel{
public $belongsTo = array('Profile');
public $hasMany = array('Milestone');
public $hasAndBelongsToMany = array(
'Skill' =>
array(
'className' => 'Skill',
'joinTable' => 'projects_skills',
'foreignKey' => 'project_id',
'associationForeignKey' => 'skill_id',
'dependent' => true,
//'conditions' => array('Advertisement.advertisement_is_active' => '1')
),
'Attachment' =>
array(
'className' => 'Attachment',
'joinTable' => 'attachments_projects',
'foreignKey' => 'project_id',
'associationForeignKey' => 'attachment_id',
)
);
public function beforeSave($options = array()) {
parent::beforeSave($options = array());
foreach (array_keys($this->hasAndBelongsToMany) as $model):
if(isset($this->data[$this->alias][$model])):
$this->data[$model][$model] = $this->data[$this->alias][$model];
unset($this->data[$this->alias][$model]);
endif;
endforeach;
return true;
}
}
Skill Model
class Skill extends AppModel {
public $name = 'Skill';
public $hasOne = array('Exam');
public $hasAndBelongsToMany = array(
'Category' =>
array(
'className' => 'Category',
'joinTable' => 'categories_skills',
'foreignKey' => 'skill_id',
'associationForeignKey' => 'category_id',
'dependent' => true
),
'Profile' =>
array(
'className' => 'Profile',
'joinTable' => 'profiles_skills',
'foreignKey' => 'skill_id',
'associationForeignKey' => 'profile_id',
'dependent' => true
),
'Project' =>
array(
'className' => 'Project',
'joinTable' => 'projects_skills',
'foreignKey' => 'skill_id',
'associationForeignKey' => 'project_id',
//'dependent' => true
)
);
}
Attachment Model
class Attachment extends AppModel{
public $name = 'Attachment';
public $hasAndBelongsToMany = array(
'Project' =>
array(
'className' => 'Project',
'joinTable' => 'attachments_projects',
'foreignKey' => 'attachment_id',
'associationForeignKey' => 'project_id',
'dependent' => true,
)
);
}
Data
Array
(
[Project] => Array
(
[project_name] => Name Of Project
[project_detail] => Dummy short description
[project_category_id] => 3
[project_budget] => 45
[Skill] => Array
(
[0] => Array
(
[skill_id] => 14
)
[1] => Array
(
[skill_id] => 16
)
)
[project_status] => 1
[project_created] => 2014-08-04 15:31:00
[creator_id] => 1
)
[Milestone] => Array
(
[milestone_name] => Milestone 1
[milestone_budget] => 45
[milestone_created_on] => 2014-08-04 15:31:00
[project_id] => 8
)
[Attachment] => Array
(
[attachment_path] => 11615297103.zip
[attachment_term] => Project Attachment
[attachment_type] => zip
[project_id] => 8
)
)
Pass Skill id not the field name of relation model
[Skill] => Array
(
[0] => Array
(
[id] => 14
)
[1] => Array
(
[id] => 16
)
)

CakePHP: HABTM relationship returns join table as an object - how do I get rid of it?

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!

cakephp habtm nested data

I have a HABTM relationship and I'd like to get nested data for a categories table from a product table something like this product array:
array(
(int) 0 => array(
'id' => (int) 1,
'name' => 'a',
'categories' => array(
(int) 0 => array(
'id' => (int) 1
),
(int) 1 => array(
'id' => (int) 2
)
)
),
(int) 1 => array(
'id' => (int) 2,
'name' => 'b',
'categories' => array(
(int) 0 => array(
'id' => (int) 1
)
)
)
)
Is this possible with cake?
EDIT: I will try to explain further what I want to do.
Please bear with me, I am new to cake and am having trouble getting to grips it.
I have a 'product' table:
public $hasAndBelongsToMany = array(
'Category' => array(
'className' => 'Category',
'joinTable' => 'categories_sculptures',
'foreignKey' => 'sculpture_id',
'associationForeignKey' => 'category_id',
'unique' => 'keepExisting'
)
)
and a category table:
public $hasAndBelongsToMany = array(
'Sculpture' => array(
'className' => 'Sculpture',
'joinTable' => 'categories_sculptures',
'foreignKey' => 'category_id',
'associationForeignKey' => 'sculpture_id',
'unique' => 'keepExisting'
)
);
and a category products table:
public $belongsTo = array(
'Category' => array(
'className' => 'Category',
'foreignKey' => 'category_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Sculpture' => array(
'className' => 'Sculpture',
'foreignKey' => 'sculpture_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
I would like to build a view table of the sculptures and also show in each row which categories each sculpture is in (which could be more than one). As I am new to cake I don't know how I would go about this. If I was just querying mysql I could get this information with a group_concat or a nested select, or inefficiently by looping through first array and querying the category_sculpture table by sculpture key and adding the results to the first array. But I would like to know the best way to get this result the cake way.
I have found the answer to my needs:
$this->Sculpture->recursive = 1;

Cakephp many to many recursive

Hy i am trying to create a follow feature to my website so user can follow each other , I am using Cakephp what kind of relation should i use , what should i name the tables.
NB: I created a user table + follow table containing user_id and follower_id !
If you don't need to save any information about the relation, then hasAndBelongsToMany is the natural relation to use in this case.
Try this:
// User Model
var $hasAndBelonsToMany = array(
'Follower' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'associationForeignKey' => 'follower_id'
'joinTable' => 'followers_users'
)
)
then you must create the users table as normal, and a table 'followers_users' with columns: 'id', 'user_id', 'follower_id' (and 'created' and 'updated' if you need them).
EDIT :
To retrieve your data (read here) you do it as usual:
$this->User->find('all', array('conditions' => array('id' => 1)));
Then you'll get an array like:
Array(
[User] => array(
[id] => 1
[name] => xxxx
)
[Follower] => array(
[0] => array(
[id] => 2
[name] => yyyy
)
[1] => array(
[id] => 3
[name] => zzzz
)
)
)
To save your data (read here and here), you need to create an array like:
array(
[User] => array(
[id] => 1
[name] => xxx
)
[Follower] => array(
[0] => array(
[id] => 2
)
[1] => array(
[id] => 3
)
)
)
Explanation of what you are looking / example is right in the book:
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#multiple-relations-to-the-same-model
Similar example per the book:
"It is also possible to create self associations as shown below:"
<?php
class Post extends AppModel {
public $name = 'Post';
public $belongsTo = array(
'Parent' => array(
'className' => 'Post',
'foreignKey' => 'parent_id'
)
);
public $hasMany = array(
'Children' => array(
'className' => 'Post',
'foreignKey' => 'parent_id'
)
);
}

Resources