将两个数组与模型合并

时间:2016-05-11 12:53:27

标签: php laravel

所以我有一个简单的表格:

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。因为我不需要它。

此外,删除了获取不同对的方法,因为它不适用。我相信它现在应该正常工作。

在完成一些更复杂的测试后会更新。

将此作为更新发布,因为我无法编辑答案。我的更正太少,无法发布我自己的答案。

2 个答案:

答案 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