Cakephp model with conditions - mysql

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

how use multiple conditions to get data from 2 HABTM tables in Cakephp 2.x

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.

Fetch random row from group by query (mysql) in Cakephp

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'
),
)
)
));

join two model from one model in cakephp

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

Model association is off for joining users table on comments table for a submission

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

How to make a variable relationship?

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