Join query in cakephp - php

Hello I am new in Cakephp and I am having a hard time converting mysql queries in cakephp.I have this query which I want to convert into Cakephp syntax
SELECT *
FROM trip
JOIN countries ON trip.departure_country_id = countries.id
WHERE countries.country_name LIKE "eng%"
This is what I have tried so far
class Trip extends AppModel
{
public $useTable = 'trip';
public $primaryKey = 'trip_id';
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'fields' => array('User.user_id','User.first_name','User.last_name','User.profile_image','User.country','User.phone_no')
),
'departure_country' => array(
'className' => 'Country',
'foreignKey' => 'departure_country_id',
),
'arrival_country' => array(
'className' => 'Country',
'foreignKey' => 'arrival_country_id',
)
);
public function getLocationBasedTrips($country){
return $this->find('all', array(
'conditions' => array(
'OR' => array('Country.country_name Like' => '%'.$country.'%')
),
));
}
}

Trip Model:
$this->find('all',
array(
'joins' => array(
array(
'table' => 'countries',
'alias' => 'Country',
'type' => 'INNER',
'conditions' => array(
'Trip.departure_country_id = Country.id'
)
),
'conditions' => array(
'Country.country_name Like' => "%$country%"
)
)
);

Moved some brackets around from the previous answer. Try this:
$this->find('all', array(
'joins' => array(
array(
'table' => 'countries',
'alias' => 'Country',
'conditions' => array(
'Trip.departure_country_id = Country.id'
)
)
),
'conditions' => array(
'Country.country_name LIKE' => "%$country%"
)
)
);

Related

Custom query pagination in cakephp

I have a query as below in controller with multiple joins
$deals = $this->Deals->find('all', array(
'fields' => array(
'Deals.id',
'Deals.deed_amount',
'Deals.other_amount',
'Deals.cash_amount',
'Deals.total_amount',
'Deals.client_id',
'Deals.project_id',
'Deals.property_id',
'Deals.properties_flat_id',
'Deals.date',
'Deals.status',
'Deals.invoice_no',
'Deals.remain_cash_amount',
'Deals.remain_deed_amount',
'Deals.remain_other_amount',
'Deals.remain_deed_amount',
'Property.name',
'Client.name',
'PropertyFlat.name',
'PropertyFlat.status'
),
'joins' => array(
array(
'table' => 'properties',
'alias' => 'Property',
'type' => 'LEFT',
'conditions' => array(
'Deals.property_id = Property.id'
)
),
array(
'table' => 'clients',
'alias' => 'Client',
'type' => 'LEFT',
'conditions' => array(
'Deals.client_id = Client.id'
)
),
array(
'table' => 'properties_flats',
'alias' => 'PropertyFlat',
'type' => 'LEFT',
'conditions' => array(
'Deals.properties_flat_id = PropertyFlat.id'
)
)
),
// 'conditions'=>$condition
));
I want to add pagination to the view. I tried following
$this->set('deals', $this->Paginator->paginate($deals));
But no use. Please help me in how to add pagination for the custom query. I searched many links but did not get any help.
You can try like this:
$paginate = [
'joins' => array(
array(
'table' => 'properties',
'alias' => 'Property',
'type' => 'LEFT',
'conditions' => array(
'Deals.property_id = Property.id'
)
),
array(
'table' => 'clients',
'alias' => 'Client',
'type' => 'LEFT',
'conditions' => array(
'Deals.client_id = Client.id'
)
),
array(
'table' => 'properties_flats',
'alias' => 'PropertyFlat',
'type' => 'LEFT',
'conditions' => array(
'Deals.properties_flat_id = PropertyFlat.id'
)
)
),
'fields' => array(
'Deals.id',
'Deals.deed_amount',
'Deals.other_amount',
'Deals.cash_amount',
'Deals.total_amount',
'Deals.client_id',
'Deals.project_id',
'Deals.property_id',
'Deals.properties_flat_id',
'Deals.date',
'Deals.status',
'Deals.invoice_no',
'Deals.remain_cash_amount',
'Deals.remain_deed_amount',
'Deals.remain_other_amount',
'Deals.remain_deed_amount',
'Property.name',
'Client.name',
'PropertyFlat.name',
'PropertyFlat.status'
)
];
$this->set('deals', $this->Paginator->paginate($this->Deals->find('all'), $paginate)->toArray());
Firstly, I would recommend to rethink the way you have constructed your query. Why don't you just use the contain() method to retrieve the associated data?
Secondly, You can use custom finders with the paginator. Just create one in your Table class and return constructed query from it and ask the paginator to use it. Read more here. https://book.cakephp.org/3.0/en/controllers/components/pagination.html

fetching data from multiple tables in Cakephp

I am new in cakephp and trying my best to implement queries in cakephp.
I have this query
SELECT * FROM question join question_topic on question.question_id=question_topic.question_id join topic on topic.topic_id=question_topic.topic_id join user_topic on user_topic.topic_id=topic.topic_id where user_topic .user_id=10
I need this in cakephp.
What I have tried is this
$this->Behaviors->attach('Containable');
return $this->find('all', array(
'contain' => array(
'User',
'UserInfo.UserTopic'=>array(
'conditions'=>array('UserTopic.user_id'=>10)
),
'QuestionAndTopic.Topic','UpVoteQuestion','Answer','Answer.UserInfo'
),
'order' => 'rand()',
'recursive' => 0
));
But the query is not giving me a right results. Could you please take a look.
Question.php
class Question extends AppModel
{
public $useTable = 'question';
public $primaryKey = 'question_id';
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'fields' => array('User.user_id','User.email','User.active')
),
'UserInfo' => array(
'className' => 'UserInfo',
'foreignKey' => 'user_id',
)
);
public $hasMany = array(
'Answer' => array(
'className' => 'Answer',
'foreignKey' => 'question_id',
),
'QuestionAndTopic' => array(
'className' => 'QuestionAndTopic',
'foreignKey' => 'question_id',
)
);
public function latestQuestions(){
$this->Behaviors->attach('Containable');
return $this->find('all', array(
'contain' => array(
'User',
'UserInfo.UserTopic'=>array(
'conditions'=>array('UserTopic.user_id'=>10)
),
'QuestionAndTopic.Topic','UpVoteQuestion','Answer','Answer.UserInfo'
),
'order' => 'rand()',
'recursive' => 0
));
}
}
You can use Mysql query it will works as like as cakephp query
$this->Behaviors->query('SELECT * FROM question join question_topic on question.question_id=question_topic.question_id join topic on topic.topic_id=question_topic.topic_id join user_topic on user_topic.topic_id=topic.topic_id where user_topic .user_id=10');
Refer this link
$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);
make changes as per you table and fields.hope this helps.

HABTM Cake php find

I have tables below with HABTM associations.
user, group , groups_users
group , project, projects_groups
public $hasAndBelongsToMany = array(
'Group' =>
array(
'className' => 'Group',
'joinTable' => 'groups_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'group_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => ''
)
);
I am trying to get all users, as a list for checkboxes, that are on a project using project id using query below
$users = $this->User->Group->Project->find('list',
array(
'conditions' => array('Project.id' => $this->Session->read('Projectid'))
,'contain' => array(
'User' => array( 'fields' => 'User.id', 'User.email')
)
)
);
But error below
Model "Project" is not associated with model "User"
I have actually tried different ways to get this working but cant seem to get it right, how can i achieve what i want. cheers
I achieved what i wanted with joins , is there a way to do this by using model associations, instead of the manual joins option?
$options['joins'] = array(
array('table' => 'groups_users',
'alias' => 'gu',
'type' => 'LEFT',
'conditions' => array(
'gu.user_id = User.id',
)
),
array('table' => 'projectGroups',
'alias' => 'pg',
'type' => 'LEFT',
'conditions' => array(
'pg.group_id = gu.group_id',
)
)
);
$this->User->recursive = -1;
$options['conditions'] = array(
'pg.project_id = ' => $this->Session->read('Projectid'),
'User.Active = ' => true
);
$users = $this->User->find('list', $options);

DISTINCT not working with hasMany cakephp

I want to apply DISTINCT query in cakephp 2+ it's working fine but when I BindModel with that model it's not working ?
Here is my code please check it..
$this->User->bindModel(
array(
'hasMany' => array(
'UserPreference' => array(
'className' => 'UserPreference',
'foreignKey' => 'user_id',
'fields' => 'UserPreference.notification_status',
'conditions' => array('UserPreference.notification_status' => 1),
)
)
)
);
$data = $this->User->find('all', array('conditions' => array('app_id NOT ' => '0', 'User.status' => 1), 'fields' => array('DISTINCT User.app_id')));
pr($data); die;
just because I once happened something like this I fix it changing this:
$this->User->bindModel(
array(
'hasMany' => array(
'UserPreference' => array(
'className' => 'UserPreference',
'foreignKey' => 'user_id',
'fields' => 'UserPreference.notification_status',
'conditions' => array('UserPreference.notification_status = 1'),
)
)
)
);

cakephp find all join

$order = $this->Order->find('all', array(
'recursive' => 2,
'conditions' => array(
'Order.date' => $datefrom,
),
'joins' => array(
array(
'table' => 'purchase',
'alias' => 'Purchase',
'conditions'=> array(
'Purchase.pid = Order.pid',
)
),
array(
'table' => 'sales',
'alias' => 'Sales',
'conditions'=> array(
'Purchase.pid = Sales.pid',
)
),
),
));
Why does the above code doesn't select fields from purchase and sales, but only fields from order are returned. What is the necessary things to be added to make all data is returned. Thanks
Try this, I'm not sure if the 'type' and 'foreignKey' keys are required, but I typically include them when using the 'joins' key. Also I'm assuming the 'pid' is the correct foreign key.
$order = $this->Order->find('all', array(
'recursive' => -1,
'conditions' => array(
'Order.date' => $datefrom,
),
'joins' => array(
array(
'table' => 'purchase',
'alias' => 'Purchase',
'type' => 'INNER',
'foreignKey' => 'pid',
'conditions'=> array(
'Order.pid = Purchase.pid',
)
),
array(
'table' => 'sales',
'alias' => 'Sales',
'type' => 'INNER',
'foreignKey' => 'pid',
'conditions'=> array(
'Sales.pid = Purchase.pid',
)
),
),
));
If you already have relationships set up in the model, change the 'recursive' key to -1.
Just an idea,
'table' => 'purchase',
'alias' => 'Purchase',
isn't a typo, is it? Because I think, the usual name for the table according to cake-conventions would be 'purchases'... But I don't know your tables of course... ;)
First you need to create an association in Order Model file
Model:
public $hasMany = array(
'purchase' => array(
'className' => 'purchase',
'foreignKey' => 'pid',
'dependent' => true,
'counterQuery' => 'true'
),
'sales' => array(
'className' => 'sales',
'foreignKey' => 'pid',
'dependent' => true,
'counterQuery' => 'true'
),
);
Controller:
$order = $this->Order->find('all', array(
'recursive' => 2,
'conditions' => array(
'Order.date' => $datefrom,
)
);
Now you can get Order, Purchase and Sales related records.
Enjoy...
Controller::loadModel('User');
Controller::loadModel('Answer');
Controller::loadModel('Influence');
$users = $this->User->find('all', array('joins' => array(
array(
'table' => 'answers',
'alias' => 'Answer',
'type' => 'inner',
'foreignKey' => false,
'conditions' => array('Answer.user_id = User.id'),
),
array(
'table' => 'influences',
'alias' => 'Influence',
'type' => 'inner',
'foreignKey' => false,
'conditions' => array(
'Influence.user_id=Answer.user_id',
)
)
),'fields' => array(
'Answer.is_correct',
'Answer.answer',
'Answer.date as answered_date',
'Influence.signups',
'Influence.clicks',
'User.first_name',
'User.last_name',
'User.email',
'User.phone',
'User.flybuys' )
));
In order to get fields from other tables You should specify the fields you want.

Categories