CakePHP paginate causing weird DISTINCT behavior - php

I have a pretty basic paginate query which works fine until I put DISTINCT on one of the columns.
The following works:
$this->paginate = array(
'conditions' => array(Message.recipient_id' => $this->Auth->user('id')),
'fields' => array(
'DISTINCT Message.sender_id',
'Message.recipient_id',
'Message.thread_id',
),
'limit' => 15,
'order' => array('Message.created' => 'DESC')
);
This query doesn't work:
$this->paginate = array(
'conditions' => array(Message.recipient_id' => $this->Auth->user('id')),
'fields' => array(
'DISTINCT Message.sender_id',
'Message.recipient_id',
'Message.thread_id',
// If I add any of the following columns, the DISTINCT doesn't work at all
'Message.created',
'Message.modified',
'Message.id'
),
'limit' => 15,
'order' => array('Message.created' => 'DESC')
);
Why would any of those other columns in the 'fields' option trip up the DISTINCT keyword?
It doesn't make any sense to me.

If you mean by "it doesn't work" that despite the distinct column you are getting multiple messages with the same sender_id... Then the reason for that is because when using multiple columns with the distinct keyword, it looks for unique combinations of all the columns. Message.created, Message.modified, and Message.id are going to be unique per row most or all of of the time, so those columns by themselves will make your combinations of fields distinct. Try using group by Message.sender_id instead.
$this->paginate = array(
'conditions' => array(Message.recipient_id' => $this->Auth->user('id')),
'fields' => array(
'Message.sender_id',
'Message.recipient_id',
'Message.thread_id',
'Message.created',
'Message.modified',
'Message.id'
),
'limit' => 15,
'order' => array('Message.created' => 'DESC'),
'group' => array('Message.sender_id'),
);

Related

Cake PHP 2 isn't joining linked hasMany relationships

I'm trying to join all AffiliateId models for each user through the Cake PHP 2 query builder, I'm seeing my users through the following query, but I get no affiliates despite there being affiliates for some users. I don't want to join affiliates if there are none for a particular user, what am I missing?
$users = $this->User->find('all', array(
'joins' => array(
array(
'table' => 'affiliate_ids',
'alias' => 'AffiliateId',
'type' => 'inner',
'conditions' => array(
'User.id = AffiliateId.user_id'
)
)
),
'order' => array(
'User.username' => 'ASC'
),
'recursive' => -1
));
So, joins will just add a join to the query, it won't select the fields. You can use fields to select them.
However, using Containable and proper associations is the better solution, as it would nest them properly in the result and would also auto select the associated fields:
$users = $this->User->find('all', array(
'contain' => array('AffiliateId'),
'order' => array('User.username' => 'ASC'),
'recursive' => -1
));

How can I convert this query in to CakePHP query?

How can I convert this query into a CakePHP query?
SELECT COUNT(invoices.id) FROM invoices,sales
WHERE invoices.id=sales.invoice_id AND to_id='13' AND is_updated='0'
GROUP BY invoice_id
I have two controllers and two models, invoices and sales.
For aggregate functions like COUNT, you need to create virtual field.
$this->Invoice->virtualFields['total'] = 'COUNT(`Invoice`.`id`)';
$result = $this->Invoice->find('all', array(
'fields' => array('Invoice.total'),
'joins' => array(
array(
'table' => 'sales',
'alias' => 'Sale',
'type' => 'INNER',
'conditions' => array(
'Invoice.id = Sale.invoice_id',
)
)
),
'conditions' => array(
'to_id' => 13,
'is_updated' => 0
),
'group' => array('Sale.invoice_id')
));
pr($result); // Check your result
Use the following links as references:
Joining tables
Retrieving Your Data
Virtual fields
Try to use Cake's Cookbook solution:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#prepared-statements

Sort forum topics by messages date relationship in cakephp

I'm using cakephp 2 framework.
I have a model "topic" with a "hasmany" relationship:
public $hasMany=array(
'Messages' => array(
'className' => 'Messages',
'foreignKey'=>'id_topic',
'dependent'=>true,
),
);
In my controller I do:
$this->paginate = array(
'Topic' => array(
'limit' => 10,
'recursive' => 2,
)
);
$entities = $this->paginate('Topic');
It works perfectly but now I would like to sort my topics by date of last message but I don't find how.
Something like:
$this->paginate = array(
'Topic' => array(
'limit' => 10,
'recursive' => 2,
'order'=>'Messages.created desc'
)
);
But I get Column not found: 1054 Unknown column 'Messages.created' in 'order clause'
Any ideas? Thanks
okay now i am showing working code for me, may be it can help you
$this->Topic->find('all');
$this->paginate = array(
//'conditions' => array('id !=' => '6'),
'limit' => 6,
'order' => array('Topic.modified' => 'desc')
);
$data = $this->paginate('Topic');
in my case i have model Topic, field modified in my topics table
Finally, I add a column in my topics table "last_message_date"
$this->paginate = array(
'Topic' => array(
'limit' => 10,
'recursive' => 2,
'order'=>array('last_message_date'=>'desc')
)
);
Not really a proper solution but I've no idea

cakephp join and mysql join

UPDATED!
i am relativly new in cakephp but having experience with mysql and php.
The model look like:
Person->Father
Father is self refered to person.
I wrote the following based on mysql query which gives back the father of "1" person
mysql:
SELECT `Father`.name,`Father`.id from persons as `Father` left join persons as `Person` on `Person`.`father_id`=`Father`.`id` where `Person`.id=1
cakephp
$options = array(
'fields' => array(
//'Father.name',
'Father.id',
),
'joins' => array(
array(
'conditions' => array(
'Person.father_id = Father.id',
),
'table' => 'persons',
// 'alias' => 'Person', i commented because having conflict with scaffolded model
'type' => 'left',
),
),
'conditions' => array(
'Person.id' => '1',
),
'contain' => array(
'Person','Father',
),
);
$data = $this->Person->find('first', $options);
$fatherquery=$this->Person->find('first',array('conditions'=>array('Person.id'=>$data['Father']['id'])));
To get the same as mysql i have add this extra line(the last one $father=....,but now it seems subquery and look like the join isn't working) because of Father and Person are not the same model and if i have
$data['Father']['name'] and $data['Person']['name'] they are not equal
By the way i have a solution already,but maybe i misunderstand some concept.
Is there a way the get the mysql query easier?
Try this. (Notice the lack of a contain. The only reason to use contain is if you're not already getting the data in the main-model's find() or a join):
//Person model (cake 2.x code)
$this->find('first', array(
'fields' => array(
'Father.id',
'Father.name'
),
'conditions' => array(
'Person.id' => 1
),
'joins' => array(
array(
'table' => 'persons',
'alias' => 'Father',
'type' => 'left',
'conditions' => array(
'Person.father_id = Father.id'
)
)
)
));

Complex paginate with NOT IN condition cakephp 2

i have a small problem to get my query work the right way.
My query should give me all lectures in the actual semester, but just those, where i'm not participating yet. So in SQL it would be:
SELECT * FROM lectures WHERE semester = $currentSemester AND lectures.id NOT IN (SELECT lectures_id FROM participaters WHERE user_id = $this->Auth->user('id'))
And what i already got is the following:
$this->paginate = array(
'conditions' => array(
'Lecture.semester >=' => $currentSemester,
'not' => array(
'Lecture.id' => array(
),
),
),
'order' => array(
'Lecture.name' => 'asc',
),
'contain' => array(
'Participater',
),
);
$this->set('lectures', $this->paginate($this->Lecture));
How can i define the condition with the user_id? Maybe someone of you can help? And sorry for my english, if here are any mistakes :)
First find a list of ids you want to exclude in the query, then use this list of ids with a condition like 'Lecture.id !=' => $ids.
Assuming you have model Participater linked to model lecture, the queries could as shown below.
//retrieve the list of excluded ids
$excluded_ids = $this->Lecture->Participater->find('list',array(
'conditions' => array(
'Participater.user_id' => $this->Auth->user('id')
),
'fields' => array('lecture_id')
);
$this->paginate = array(
'conditions' => array(
'Lecture.semester >=' => $currentSemester,
'Lecture.id !=' => $excluded_ids,//put the excluded ids here
),
'order' => array(
'Lecture.name' => 'asc',
),
'contain' => array(
'Participater',
),
);
$this->set('lectures', $this->paginate($this->Lecture));

Categories