Association of models(JOIN) not working in cakephp, shows empty results - mysql

I am purely new to cakephp and currently working on a project that is built in version 1.3. Basically I am trying to display the city names of the providers which are inserted in the database.
I have two models : gal_store.php and gal_location.php. In the gal_store model, the stores names are saved with their corresponding city ids in city field in gal_stores table. The table gal_locations contains all the cities and their names.
So I tried to JOIN the two tables as below :
var $hasOne = array(
'GalLocation' => array(
'className' => 'GalLocation',
'foreignKey' => 'id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
function getList($limit = 50,$whether_list = false){
$recursive = -1;
$conditions = array("GalStore.city"=> "GalLocation.id");
//$conditions = "";
$order = array("GalStore.address");
if($whether_list == true){
return $this->find("list",array("DISTINCT GalStore.city","recursive"=>$recursive,"limit"=>$limit,"order"=>$order,"conditions" => $conditions));
}else{
return $this->find("all",array("DISTINCT GalStore.city","recursive"=>$recursive,"limit"=>$limit,"order"=>$order,"conditions" => $conditions));
}
}
But in the ctp file when I do a var_dump($gal_locations); it always shows empty ! What is the reason ?

If the gal_locations has one to one relationship with gal_stores, use below code:
var $hasOne = array(
'GalLocation' => array(
'className' => 'GalLocation',
'foreignKey' => 'city',//if the city field contains the id of gal_locations table
'conditions' => '',
'fields' => '',
'order' => ''
),
);
If the gal_locations has one to many relationship with gal_stores, use below code:
var $belongsTo = array(
'GalLocation' => array(
'className' => 'GalLocation',
'foreignKey' => 'city',//if the city field contains the id of gal_locations table
'conditions' => '',
'fields' => '',
'order' => ''
),
);

Related

cakephp virtual fields with subquery and if

I have a Category table with a name field.
I want to be able to overwrite that name using a PartnerCategory Table and join it.
So usually I would get the Category like this:
$options = array(
'contain' => array('PartnerCategory'),
'conditions' => array(
'Category.slug' => $slug,
'Category.status' => true,
)
);
$category = $this->Category->find('first', $options);
And then check, if ParentCategory.name is not empty and replace the Category.name with it.
Overwriting the name with php is tedious so I checked virtual fields.
I can overwrite the Category.name using this:
$this->virtualFields = array(
'name' => 'SELECT name FROM app_partner_categories WHERE category_id = 1 AND partner_id = 60'
);
But if the name in the PartnerCategory table is empty or no mathes are found, the Category.name would be null.
How can I overwrite Category.name only if PartnerCategory.name is found?
Not sure but this could be a possible solution:
$joins = array(array('table' => 'app_partner_categories',
'alias' => 'PartnerCategory',
'type' => 'INNER',
'conditions' => array(
'PartnerCategory.category_id = Category.id'
)
)
);
$options = array(
'fields' => array('IF(PartnerCategory.name IS NULL or PartnerCategory.name = "", Category.name, PartnerCategory.name) as overwritten_name'),
'joins' => $joins,
'conditions' => array(
'Category.slug' => $slug,
'Category.status' => true,
)
);
$category = $this->Category->find('first', $options);

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

Retrieving Data From two tables that are associated with a forign key in CakePhp

I have two tables named login and userDetail
Login
login_id
uname
pswd
userdetail_id
and
userdetails
userdetail_id
name
address
email
the login table contain userdetails_id in the userDetail table. i want to get all data from Login table and userDetail table and save it to a variable
if anyone knows, please answer me......
First of all your table structure must be as below.
logins Table.
Id auto_increment
username
password
userDetails Table.
Id auto_increment
user_id
name
address
etc...
Now model for each table would be.
Login
<?php
class Login extends AppModel
{
var $name = 'User';
var $hasMany = array
(
'UserDetail' => array
(
'className' => 'UserDetail',
'foreignKey' => 'user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
}
?>
UserDetail
<?php
class UserDetail extends AppModel
{
var $name = 'UserDetail';
var $belongsTo = array
(
'User' => array
(
'className' => 'User',
'foreignKey' => 'user_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => ''
)
}
?>
And finally in controller where you need to fetch login detail.
$login_detail = $this->Login->find('all');
You will see userDetail table records in resulting $login_detail.
use pr($login_detail); in controller to see it in action.
Cheers.
Feel Free to ask.
Make sure ContainableBehavior has been enabled. After that you can use following query:
$login = $this->Login->find('first', array(
'contain' => array(
'Userdetail.userdetail_id'
'Userdetail.name',
'Userdetail.address',
'Userdetail.email'
),
'fields' => array(
'Login.login_id'
'Login.uname',
'Login.pswd'
),
'conditions' => array(
'Login.login_id' => 1
)
));
The query for this task would be:
SELECT Login.*, name,address,email
FROM Login JOIN userdetails
ON Login.userdetail_id=userdetails.userdetail_id
The results of this query could be saved to variables by looping in cakephp.

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

Cakephp model with conditions

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(
...
)
)
);