drgzmmy6379 2016-05-11 12:53
浏览 118
已采纳

将两个数组与模型合并

So I have a simple table:

messages:
 - id
 - user_id - user that "sent" the message (the author)
 - to_user_id - user that "received" the message
 - body
 - created_at
 - updated_at

I'm using Laravel 5.2, I have a model that looks like this:

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');
    }
}

In my controller I have two variables that call few model methods:

$this->sent = Message::sentByUser(Auth::user()->id)->newestFirst()->get();
$this->received = Message::receivedByUser(Auth::user()->id)->newestFirst()->get();

I was wondering how can I merge them into threads. Basically I don't have anything like threads in my app. Users can write messages between and it's a single thread. Like Zuckerberg's social network, or Google's chat client.

I want to be able to keep them in order (or I can order them after grouping) and have something like:

$threads = [
    [
        'participants' => [1, 2], //those are users' ids
        'messages' => [
            (Model)Message,
            (Model)Message,
            (Model)Message,
            (Model)Message,
            (Model)Message
        ]
    ] 
];

Edit:

Based on the accepted answer I ended up having the following code:

$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;

The differences are: pluck() is replaced with lists()->toArray()

After merging the arrays (array_merge) and picking the unique values only (array_unique) I unset the logged in user's id. Because I don't need it.

Also, removed that method for getting the distinct pairs, since it's not applicable. I believe it should be working now properly.

Will update after some more complex testing is done.

Posted this as update, since I cannot edit answers. And my corrections are too few to post my own answer.

  • 写回答

2条回答 默认 最新

  • duannong1801 2016-05-11 14:25
    关注

    Something like this should work. I've written it like a model method, but you can also add it to a controller by changing $this to the correct model name.

    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条)

报告相同问题?

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥15 绘制多分类任务的roc曲线时只画出了一类的roc,其它的auc显示为nan
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?