所以我有一个简单的表格:
messages:
- id
- user_id - user that "sent" the message (the author)
- to_user_id - user that "received" the message
- body
- created_at
- updated_at
我使用的是Laravel 5.2,我的模型看起来像这样:
class Message extends Model
{
public function user()
{
return $this->belongsTo('App\Models\User'); //This should return only the sender
}
public function scopeSentByUser($query, $user_id)
{
return $query->where('user_id', '=', $user_id);
}
public function scopeReceivedByUser($query, $user_id)
{
return $query->orWhere('to_user_id', '=', $user_id);
}
public function scopeNewestFirst($query)
{
return $query->orderBy('created_at', 'DESC');
}
}
在我的控制器中,我有两个调用几个模型方法的变量:
$this->sent = Message::sentByUser(Auth::user()->id)->newestFirst()->get();
$this->received = Message::receivedByUser(Auth::user()->id)->newestFirst()->get();
我想知道如何将它们合并到线程中。基本上我在我的应用程序中没有像线程一样的东西。用户可以在它之间编写消息,它是一个单独的线程。像扎克伯格的社交网络,或谷歌的聊天客户端。
我希望能够将它们整理好(或者我可以在分组后对它们进行订购)并且有类似的东西:
$threads = [
[
'participants' => [1, 2], //those are users' ids
'messages' => [
(Model)Message,
(Model)Message,
(Model)Message,
(Model)Message,
(Model)Message
]
]
];
修改:
根据接受的答案,我最终得到以下代码:
$query = self::where('user_id', $logged_user_id)->orWhere('to_user_id', $logged_user_id)->get();
$inUserId = $query->lists('user_id')->toArray();
$inToUserId = $query->lists('to_user_id')->toArray();
$mergedIds = array_merge($inUserId, $inToUserId);
$uniqueIds = array_unique($mergedIds);
unset($uniqueIds[array_search($logged_user_id, $uniqueIds)]); //Remove logged in user ID
$combinations = [];
foreach ($uniqueIds as $id) {
$combinations[] = [$id, $logged_user_id];
}
$threads = [];
foreach ($combinations as $key => $combo) {
$threads[] = [
'receiver' => $combo[0] == $logged_user_id ? User::find($combo[1]) : User::find($combo[0]),
'messages' => self::where(function ($query) use ($combo) {
$query->where('user_id', $combo[0])->where('to_user_id', $combo[1]);
})->orWhere(function ($query) use ($combo) {
$query->where('user_id', $combo[1])->where('to_user_id', $combo[0]);
})->orderBy('created_at', 'ASC')->get()
];
}
return $threads;
不同之处在于:
pluck()
替换为lists()->toArray()
合并数组(array_merge
)并仅选择唯一值(array_unique
)后,我取消设置登录用户的ID。因为我不需要它。
此外,删除了获取不同对的方法,因为它不适用。我相信它现在应该正常工作。
在完成一些更复杂的测试后会更新。
将此作为更新发布,因为我无法编辑答案。我的更正太少,无法发布我自己的答案。
答案 0 :(得分:1)
这样的事情应该有效。我已将它写成模型方法,但您也可以通过将$this
更改为正确的型号名称将其添加到控制器中。
public function getThreads($id) {
$query = $this->where('user_id', $id)->orWhere('to_user_id', $id)->get();
// get the unique user id's
$user_ids = array_unique (array_merge ($query->pluck('user_id'), $query->pluck('to_user_id')));
// get the distinct pairs
// taken from here: http://stackoverflow.com/a/3770452/485418
$num_ids = count($user_ids);
for ($i = 0; $i < $num_ids; $i++)
{
for ($j = $i+1; $j < $num_ids; $j++)
{
$combinations[] = array($user_ids[$i], $user_ids[$j]);
}
}
$threads = array();
$tmp = array();
// build the threads array
foreach ($combinations as $key => $combo) {
$tmp = array();
$tmp['participants'] = $combo;
$tmp['messages'] = $this->where(function($query) {
$query->where('user_id', $combo[0])->where('to_user_id', $combo[1]);
})->orWhere(function($query) {
$query->where('user_id', $combo[1])->where('to_user_id', $combo[0]);
})->orderBy('created_at', 'DESC')->get();
$threads[] = $tmp;
}
return $threads
}
答案 1 :(得分:0)
也许是这样的:
$messages = array();
foreach ($this->sent as $message) {
$messages[] = $message;
}
foreach ($this->received as $message) {
$messages[] = $message;
}
$messages = collect($messages);
$participants = $messages->keyBy('user_id')->keys();
如果你有集合$messages
,你可以使用所有这些方法:https://laravel.com/docs/master/collections