1

我正在尝试获取与其相应用户的消息,以便按时间顺序显示个人资料的聊天列表以及他们的最后一条消息。

array(
    0 => array(
        'Recepient' => array(
            'id' => ...
            'name' => ...
            ...
        ),
        'Message' => array(
            'content' => ...
            'created' => ...
            ...
        )
    ),
    1 => ...
)

为了检索结果,我编写了这个 find() 方法:

$msgs = $this->Message->find('all', array(
    'group' => array('Recepient.id'),
    'order'=>'Message.created DESC',
    'conditions'=>
        array(
            'OR'=> array(
                array('recepient_id'=>$pid),
                array('sender_id' => $pid)
            )
    )
));

我有的:

  • 带有相应“收件人”的消息,
  • 按年代顺序

问题:

  • 查询不会从 $recepient_id/$sender_id 组合中检索最新消息。

因此,我有一个带有消息的用户列表,而不是带有最后一条消息的用户列表。我的查询有什么问题?感谢帮助!

方法 2 结果

我在数据库中创建了“chat_id”字段,它基本上是按字母顺序排序的recepient_id+sender_id(因为如果user1向user2发送消息user1是发送者,稍后当user2响应时,他成为发送者,所以排序将确保两个用户总是有相同的chat_id)。

比我在查询中添加了 DISTINCT :

$this->Message->recursive = 0; $msgs = $this->Message->find('all', array( 'fields' => array('DISTINCT Message.chat_id','Message.*','Recepient.*'), 'order'=>'Message.created DESC', 'conditions'=> array( 'OR'=> array( array('recepient_id'=>$pid), array('sender_id' => $pid) ) ) ));

它不起作用!我现在收到同一对话的多条消息。

如果我从查询中删除消息字段和收件人字段,我会得到正确数量的“聊天”。 'fields' => array('DISTINCT Message.chat_id'), 但这不是解决方案。

CakePHP 2.7.0 版 MySQL 数据库

方法 3 结果

$msgs = $this->Message->find('all', array( 'order'=>'Message.created DESC', 'fields' => 'recepient_id, content, max(Message.created) as max_created', 'group'=>'recepient_id', // 'contain' => array('Recepient'), 'conditions'=>array( 'chat_id' => $chats ) ));

我放弃了单一查找方法来解决这个问题,所以现在 1.我正在获取聊天列表,2.我想从每个聊天中找到最后一条消息。根据http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/我的 find 查询应该可以工作。发生的事情是

(int) 0 => array(
        'Message' => array(
            'recepient_id' => '55e6d764-1444-4aad-a909-9042f07f76da',
            'content' => '1st msg',
            'created' => '2015-09-20 18:24:17',
            'created_nice' => '2  hours ago'
        ),
        (int) 0 => array(
            'max_created' => '2015-09-20 18:24:28'
        )
    ),

创建的字段max(Message确实显示了来自对话的最新消息,但 0=>Message 数组用于不同的消息!正如你所看到的时间和不同的!.)$results[0]['Message']['created']$results[0][0]['max_created']

4

1 回答 1

2

Finally! Working solution:

$db = $this->Message->getDataSource();
$chats = $db->fetchAll(
    'select id from (select * from messages order by created desc) Message
    where recepient_id = "'.$pid.'" or sender_id = "'.$pid.'"
    group by `chat_id`'
);

Above code will retrieve all messages, following the requirements. You can

a) SINGLE QUERY add mysql JOIN to include associated model (we keep the code single-query neat)

b) TWO QUERIES BUT SMARTER easier method, to select just "ids" of the messages and create another query that will have cake's build in containable behaviour. This might be better also because Behaviours will be applied.

You will have array tree as a result, to dig out the actual ids for next query use following:

$chats = Set::extract("/Message/id",$chats);

c) translate the solution to CakePHP query builder... :) up for a challenge?

于 2015-09-20T20:38:45.753 回答