我有三个模特
模型关系
user有belongsToMany('App\Channel');channel有hasMany('App\Reply', 'channel_id', 'id')->oldest();假设我有两个频道-频道-1-频道-2频道
channel-2比channel-1有最新的回复
现在,我想通过用户频道的当前回复来订购用户的频道。就像一些聊天应用程序。我怎样才能像这样订购用户的频道?
我已经试过一些密码了。但什么都没发生
// 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编辑,我也试过这个。是的,我确实得到了预期的结果,但如果没有回复,它不会加载所有通道。
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');
}编辑:


发布于 2016-11-28 07:40:34
据我所知,急切加载 with方法运行第二次查询。这就是为什么您不能通过急切地加载 with方法来实现您想要的结果。
笔者认为,采用join法与关系法相结合的是解决方案。以下解决方案经过充分测试,运行良好。
// 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方法即可。
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方法,实现如下所示。
return $this->channels()
->leftJoin('replies', 'channels.id', '=', 'replies.channel_id')
->groupBy(['channels.id'])
->orderByRaw('max(replies.created_at) desc')
->get();发布于 2019-05-24 18:38:03
在您的通道类中,您需要创建这个hasOne关系(通道hasMany 答复,但它是hasOne 最新回复):
public function latestReply()
{
return $this->hasOne(\App\Reply)->latest();
}您现在可以从最新的回复中获得以下所有频道:
Channel::with('latestReply')->get()->sortByDesc('latestReply.created_at');要从最新回复命令的用户获得所有通道,您将需要这样的方法:
public function getChannelsOrderdByLatestReply()
{
return $this->channels()->with('latestReply')->get()->sortByDesc('latestReply.created_at');
}其中,channels()是通过以下方式提供的:
public function channels()
{
return $this->belongsToMany('App\Channel');
}发布于 2016-11-28 08:18:49
首先,如果遵循拉勒维尔命名惯例,则不必指定pivot表的名称,这样代码看起来就更简洁了:
public function channels()
{
return $this->belongsToMany('App\Channel') ...其次,必须显式调用join才能在一个查询中获得结果:
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');
}https://stackoverflow.com/questions/40837690
复制相似问题