Is it possible to make relation in cakephp model with some specific conditions:
eg:
var $belongsTo = array(
'Parent' => array(
'className' => 'Category',
'foreignKey' => 'parent_id',
'dependent' => true
)
);
I want the above relation on where field parent_id is not 0. Please give some overview on How to do that?
You can put conditions in the relations just like you do with finds.
var $belongsTo = array(
'Parent' => array(
'className' => 'Category',
'foreignKey' => 'parent_id',
'dependent' => true,
'conditions' => array(
...
)
)
);
Related
I'm trying to get only those products which have specific brand and category.
in Product model i used this query
$products = $this->find('all', array(
'joins' => array(
array('table' => 'brands_products',
'alias' => 'BrandsProducts',
'type' => 'INNER',
'conditions' => array(
'BrandsProducts.brand_id' => $brandId,
'BrandsProducts.product_id = Product.id'
)
)
),
'group' => 'Product.id'
));
By using above query i can get only those products which has specific brand id.
Exactly i don't know how to use multiple conditions to get data from 2 HABTM tables.
in my example product HABTM relation with Category and Brands.
$products = $this->find('all', array(
'joins' => array(
array('table' => 'brands_products',
'alias' => 'BrandsProducts',
'type' => 'INNER',
'conditions' => array(
'BrandsProducts.brand_id' => $brandId,
'BrandsProducts.product_id = Product.id'
)
),
array('table' => 'categories_products',
'alias' => 'CategoriesProducts',
'type' => 'INNER',
'conditions' => array(
'CategoriesProducts.category_id' => $categoriesId,
'CategoriesProducts.product_id = Product.id'
)
)
),
'group' => 'Product.id'
));
By using this query i got error in db. SO i'm looking how to write proper query to get only those products where brand and category match.
I have a table 'activities' and the columns are grouped by three of its attributes. Now I want to fetch Activity ID that is randomly selected from all the set of groups. The query is as follows:
$act = $this->find('all', array('conditions' => $cond,
'limit' => $limit,
'fields' => array('count(*) as count, Activity.id as id'),
'page' => $page,
'group' => $group,
));
These are the things I tried and none of them worked.
1. Create a self join which should have random records
$this->bindModel(array(
'belongsTo' => array(
'Random' => array(
'className' => 'Activity',
'order' => 'rand()',
'foreignKey' => 'id',
'fields' => 'Random.id'
)
)
));
This failed because the rand() order is appended in the end which simply randomizes all fetched activities.
Added a join option
'joins' => array(
array(
'table' => 'activities',
'alias' => 'Random',
'type' => 'LEFT',
'conditions' => array(
'Activity.id = Random.id'
),
'fields' => 'Random.id',
'order' => 'rand()'
)
This also didn't work as order value is not parsed by Cake
Tried to add condition
'Activity.id >= floor(rand() * (max(Activity.id) - min(Activity.id)) - min(Activity.id))'
Gave a mysql error
Please help me out
Assuming that your query is working:
$act = $this->find('all', array('conditions' => $cond,
'limit' => $limit,
'fields' => array('count(*) as count, Activity.id as id'),
'page' => $page,
'group' => $group,
'order' => 'rand()',
'limit' => '1' // if you only want one random activity ID
));
Ok finally figured it out. We need to hack the way cake php works. In place of table name, I wrote a query to fetch randomly ordered records. Also notice the join type is 'right'. Left join wont produce randomly sorted list
$activities = $this->find('all', array('conditions' => $cond,
'page' => $page,
'limit' => $limit,
'fields' => array('count(*) as count, Random.id as id, max(Activity.modified) as Modified'),
'group' => $group,
'order' => 'Modified desc',
'joins' => array(
array(
'table' => '(select * from activities order by rand())',
'alias' => 'Random',
'type' => 'RIGHT',
'conditions' => array(
'Activity.id = Random.id'
),
)
)
));
i want to fetch record form 2 model (Booking and Message), both model don't have any relation.
i try a lot but its not working
i used that code ( http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables )
$options['joins'] = array(
array('table' => 'books_tags',
'alias' => 'BooksTag',
'type' => 'inner',
'conditions' => array(
'Book.id = BooksTag.book_id'
)
),
array('table' => 'tags',
'alias' => 'Tag',
'type' => 'inner',
'conditions' => array(
'BooksTag.tag_id = Tag.id'
)
)
);
$options['conditions'] = array(
'Tag.tag' => 'Novel'
);
$books = $Book->find('all', $options);
Try this:
BookModel:
public $hasMany = array(
'BooksTag' => array(
'foreignKey' => 'book_id'
)
);
TagModel:
public $hasMany = array(
'BooksTag' => array(
'foreignKey' => 'tag_id'
)
);
BooksController:
$this->Book->Behaviors->load('Containable');
$this->Book->find('all', array(
'contain' => array(
'BooksTag' => array(
'Tag',
),
),
));
I prefer to do this on many queries. First find the required tag:
$this->loadModel('Tag');
$tag = $this->Tag->find('first', array('conditions' => array('Tag.tag' => 'Novel')));
$tag_id = $tag['Tag']['id'];
Then find book_ids:
$this->loadModel('BookTag');
$book_ids = $this->BookTag->find('list', array('conditions' => 'BookTag.tag_id' => $tag_id, 'fields' => 'book_id, book_id'));
Then find books:
$this->Book->find('all', array('conditions' => array('Book.id' => $book_ids)));
It is a long code but runs fast and is easy to understand. Another way is to use sub-queries but they are ugly and may slow down your application
My associations in CakePHP are a bit off. Here is the problem. I have a users table
and a comments table. When retrieving a submission I want to join the users table
on the comments table with Comment.user_id == User.id.
Comment Model:
class Comment extends AppModel {
var $name = 'Comment';
var $belongsTo = array('User');
var $hasMany = array(
'CommentsLike' => array(
'className' => 'CommentsLike'
),
'Comment' => array(
'className' => 'Comment'
)
);
var $hasAndBelongsToMany = array(
'User' => array(
'className' => 'User',
'joinTable' => 'comments',
'foreignKey' => 'Comment.user_id',
'associationForeignKey' => 'user_id'
),
'Submission' => array(
'className' => 'Submission'
)
);
User Model:
class User extends AppModel {
var $name = 'User';
var $hasMany = array('Comment');
var $hasAndBelongsToMany = array(
'Comment' => array(
'className' => 'Comment',
'joinTable' => 'comments',
'foreignKey' => 'Comment.user_id',
'associationForeignKey' => 'user_id',
),
'Submission' => array(
'className' => 'Submission',
'order' => 'Submission.created DESC'
)
);
When I grab a submission, it grabs all comments for it, but it doesn't join on
the users table which is what I want
Submission Model:
class Submission extends AppModel {
var $name = 'Submission';
var $belongsTo = array(
'User' => array(
'className' => 'User'
)
);
var $hasMany = array(
'Comment' => array(
'className' => 'Comment',
'order' => 'Comment.created DESC',
'conditions' => array(
'Comment.deleted' => 0
)
),
'SubmissionsVote' => array(
'className' => 'SubmissionsVote'
),
'SubmissionThumbnails' => array(
'className' => 'SubmissionThumbnails'
)
);
A find on a submission will return this:
[Submission] => Array
(
// removed for sake of stackoverflow length
)
[User] => Array
(
[id] => 2
[username] => bob_cobb
)
[Comment] => Array
(
[0] => Array
(
[id] => 1
[submission_id] => 112
[comment] => this is a test comment
[user_id] => 2
[created] => 5 minutes ago
[deleted] =>
[parent_id] =>
)
)
As you can see [Comment][0] should also have [Comment][0][User] or something similar.
Why would I want this? Simple: I want to grab the username of the person who
commented by the foreign key of user_id from the comments table. I've read the docs and tutorials and pretty sure I'm close on this but not sure what's holding me back.
Here is a screenshot of the comments table:
Here is a screenshot of the users table structure:
You can a couple of options:
Either set the recursive property in the Submission model to the level you need to fetch back your associated data ( see http://book.cakephp.org/2.0/en/models/model-attributes.html#recursive )
or (more preferable) use the Containable behaviour ( see http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html ) to specify what related data to return:
class Submission extends AppModel
public $actsAs = array('Containable');
}
Use it like this in your find:
$data = $this->Submission->find('all', array(
'conditions'=>array(your conditions here),
'contain'=>array(
'User,
'Comment'=>array(
'User'
)
)
));
Most people use containable in every model so add it to AppModel and set AppModel::recursive to -1
Each Comment can be the child of either a Question, a Game, or a User. I designed the table so that it has two fields to manage the relationship, parent_type and parent_id. I do not understand how I would make this relationship work with CakePHP 2.1.. I know it is a belongsTo relationship, but how would I specify the table to which it belongs based on another field in that table?
Comments model
var $belongsTo = array(
'Question' => array('className' => 'Question', 'foreignKey' => 'id'),
'Game' => array('className' => 'Game', 'foreignKey' => 'id'),
'User' => array('className' => 'User', 'foreignKey' => 'id'));
Questions model
var $hasMany = array(
'Comment' => array(
'className' => 'Comment',
'foreignKey' => 'parent_id',
'conditions' => array('Comment.parent_type' => 'question')
)
);
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html