首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >拉拉威尔口才

拉拉威尔口才
EN

Stack Overflow用户
提问于 2016-11-28 05:27:19
回答 4查看 39.7K关注 0票数 18

我有三个模特

  • 用户
  • 频道
  • 回复

模型关系

  • userbelongsToMany('App\Channel');
  • channelhasMany('App\Reply', 'channel_id', 'id')->oldest();

假设我有两个频道-频道-1-频道-2频道

channel-2channel-1有最新的回复

现在,我想通过用户频道的当前回复来订购用户的频道。就像一些聊天应用程序。我怎样才能像这样订购用户的频道?

  • 频道-2
  • 频道-1

我已经试过一些密码了。但什么都没发生

代码语言:javascript
复制
// User Model
public function channels()
    {
        return $this->belongsToMany('App\Channel', 'channel_user')
                    ->withPivot('is_approved')
                    ->with(['replies'])
                    ->orderBy('replies.created_at'); // error

    }
// also
public function channels()
    {
        return $this->belongsToMany('App\Channel', 'channel_user')
                    ->withPivot('is_approved')
                    ->with(['replies' => function($qry) {
                        $qry->latest();
                    }]);
    }
// but i did not get the expected result

编辑,我也试过这个。是的,我确实得到了预期的结果,但如果没有回复,它不会加载所有通道。

代码语言:javascript
复制
public function channels()
{
    return $this->belongsToMany('App\Channel')
                ->withPivot('is_approved')
                ->join('replies', 'replies.channel_id', '=', 'channels.id')
                ->groupBy('replies.channel_id')
                ->orderBy('replies.created_at', 'ASC');
}

编辑:

EN

回答 4

Stack Overflow用户

发布于 2016-11-28 07:40:34

据我所知,急切加载 with方法运行第二次查询。这就是为什么您不能通过急切地加载 with方法来实现您想要的结果。

笔者认为,采用join法与关系法相结合的是解决方案。以下解决方案经过充分测试,运行良好。

代码语言:javascript
复制
// In User Model
public function channels()
{
    return $this->belongsToMany('App\Channel', 'channel_user')
        ->withPivot('is_approved');
}

public function sortedChannels($orderBy)
{
    return $this->channels()
            ->join('replies', 'replies.channel_id', '=', 'channel.id')
            ->orderBy('replies.created_at', $orderBy)
            ->get();
}

然后,您可以调用$user->sortedChannels('desc')来获得通道的列表,通过答复created_at属性获得顺序。

对于像通道这样的条件(可能有也可能没有答复),只需使用leftJoin方法即可。

代码语言:javascript
复制
public function sortedChannels($orderBy)
    {
        return $this->channels()
                ->leftJoin('replies', 'channel.id', '=', 'replies.channel_id')
                ->orderBy('replies.created_at', $orderBy)
                ->get();
    }

编辑:

如果要将groupBy方法添加到查询中,则必须特别注意orderBy子句。因为在Sql性质中,Group By子句首先运行于Order By子句之前。请参阅在这个堆叠溢出问题上详细介绍这个问题。

因此,如果添加groupBy方法,则必须使用orderByRaw方法,实现如下所示。

代码语言:javascript
复制
return $this->channels()
                ->leftJoin('replies', 'channels.id', '=', 'replies.channel_id')
                ->groupBy(['channels.id'])
                ->orderByRaw('max(replies.created_at) desc')
                ->get();
票数 18
EN

Stack Overflow用户

发布于 2019-05-24 18:38:03

在您的通道类中,您需要创建这个hasOne关系(通道hasMany 答复,但它是hasOne 最新回复):

代码语言:javascript
复制
public function latestReply()
{
    return $this->hasOne(\App\Reply)->latest();
}

您现在可以从最新的回复中获得以下所有频道:

代码语言:javascript
复制
Channel::with('latestReply')->get()->sortByDesc('latestReply.created_at');

要从最新回复命令的用户获得所有通道,您将需要这样的方法:

代码语言:javascript
复制
public function getChannelsOrderdByLatestReply()
{
    return $this->channels()->with('latestReply')->get()->sortByDesc('latestReply.created_at');
}

其中,channels()是通过以下方式提供的:

代码语言:javascript
复制
public function channels()
{
    return $this->belongsToMany('App\Channel');
}
票数 3
EN

Stack Overflow用户

发布于 2016-11-28 08:18:49

首先,如果遵循拉勒维尔命名惯例,则不必指定pivot表的名称,这样代码看起来就更简洁了:

代码语言:javascript
复制
public function channels()
{
    return $this->belongsToMany('App\Channel') ...

其次,必须显式调用join才能在一个查询中获得结果:

代码语言:javascript
复制
public function channels()
{
    return $this->belongsToMany(Channel::class) // a bit more clean
        ->withPivot('is_approved')
        ->leftJoin('replies', 'replies.channel_id', '=', 'channels.id') // channels.id
        ->groupBy('replies.channel_id')
        ->orderBy('replies.created_at', 'desc');
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40837690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档