按最新(最新)相关型号排序 [Laravel]
Order by the latest (most recent) related model [Laravel]
我正在使用 Laravel 5.4 并且我有以下关系:
- 论坛
hasMany
主题 (threads()
)
- 线程
hasMany
Post (posts()
)
- 线程
belongsTo
用户 (user()
)
- Post
belongsTo
用户 (user()
)
目前,在我的 ThreadsController@index
中,我有以下内容:
public function index()
{
$threads = $this->forum->threads()
->approved()
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}]
)
->with('user') // Author of thread
->latest()
->paginate(20);
return view('forums.threads.index')->with([
'forum' => $this->forum, 'threads' => $threads
]);
}
我的 index.blade.php
应该显示 threads 的列表,其中每个 thread 将有:
- 它的作者(这就是为什么我有
->with('user')
)
- 回复数量(这就是为什么我有
>withCount(['posts AS approved_replies' => function ($query) { ...
)
最新(最新)日期post及其作者。这就是为什么:
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest(); // LATEST first
}]
)
... 因为在 index.blade.php
中我可以通过以下方式访问每个线程的最新 post:
@foreach ($threads as $thread)
{{ $thread->posts->first()->created_at; }}
{{ $thread->posts->first()->user->username; }}
@endforeach
此代码的问题在于 线程 按它们的 created_at
排序,而不是按最近的 post 排序。我想实现的是按最新(最近)post来订购threads,但我不知道如何这样做。
您需要使用join()
:
$threads = Thread::join('posts as p', 'p.thread_id', '=', 'threads.id')
->where('forum_id', $this->forum->id)
->approved()
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}]
)
->with('user') // Author of thread
->latest('p.created_at')
->paginate(20);
这是我的做法。它不是特别漂亮,但应该可以完成工作
$this->forum->threads()
->approved()
->join('posts', 'posts.thread_id', '=', 'threads.id')
->selectRaw('threads.*, MAX(posts.created_at) AS latest_post_at')
->groupBy('threads.id')
->orderByDesc('latest_post_at')
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}]
)
->with('user')
->paginate(20);
它按照其他答案的建议执行 join
,然后按线程 groups
,使用 MAX
聚合函数来保持每组帖子的最新日期。
编辑:
$this->forum->threads()
->approved()
->join('posts', 'posts.thread_id', '=', 'threads.id')
->select('threads.*', 'posts.created_at AS latest_post_at')
->whereNotExists(function ($subquery) {
return $subquery->from('posts AS later_posts')
->whereRaw('later_posts.thread_id = posts.thread_id')
->whereRaw('later_posts.created_at > posts.created_at');
})
->orderByDesc('latest_post_at')
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)
->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}])
->with('user')
->paginate(20);
我正在使用 Laravel 5.4 并且我有以下关系:
- 论坛
hasMany
主题 (threads()
) - 线程
hasMany
Post (posts()
) - 线程
belongsTo
用户 (user()
) - Post
belongsTo
用户 (user()
)
目前,在我的 ThreadsController@index
中,我有以下内容:
public function index()
{
$threads = $this->forum->threads()
->approved()
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}]
)
->with('user') // Author of thread
->latest()
->paginate(20);
return view('forums.threads.index')->with([
'forum' => $this->forum, 'threads' => $threads
]);
}
我的 index.blade.php
应该显示 threads 的列表,其中每个 thread 将有:
- 它的作者(这就是为什么我有
->with('user')
) - 回复数量(这就是为什么我有
>withCount(['posts AS approved_replies' => function ($query) { ...
) 最新(最新)日期post及其作者。这就是为什么:
->with(['posts' => function ($query) { // Posts $query->approved() ->with('user') // Author of post ->latest(); // LATEST first }] )
... 因为在
index.blade.php
中我可以通过以下方式访问每个线程的最新 post:@foreach ($threads as $thread) {{ $thread->posts->first()->created_at; }} {{ $thread->posts->first()->user->username; }} @endforeach
此代码的问题在于 线程 按它们的 created_at
排序,而不是按最近的 post 排序。我想实现的是按最新(最近)post来订购threads,但我不知道如何这样做。
您需要使用join()
:
$threads = Thread::join('posts as p', 'p.thread_id', '=', 'threads.id')
->where('forum_id', $this->forum->id)
->approved()
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}]
)
->with('user') // Author of thread
->latest('p.created_at')
->paginate(20);
这是我的做法。它不是特别漂亮,但应该可以完成工作
$this->forum->threads()
->approved()
->join('posts', 'posts.thread_id', '=', 'threads.id')
->selectRaw('threads.*, MAX(posts.created_at) AS latest_post_at')
->groupBy('threads.id')
->orderByDesc('latest_post_at')
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}]
)
->with('user')
->paginate(20);
它按照其他答案的建议执行 join
,然后按线程 groups
,使用 MAX
聚合函数来保持每组帖子的最新日期。
编辑:
$this->forum->threads()
->approved()
->join('posts', 'posts.thread_id', '=', 'threads.id')
->select('threads.*', 'posts.created_at AS latest_post_at')
->whereNotExists(function ($subquery) {
return $subquery->from('posts AS later_posts')
->whereRaw('later_posts.thread_id = posts.thread_id')
->whereRaw('later_posts.created_at > posts.created_at');
})
->orderByDesc('latest_post_at')
->withCount(['posts AS approved_replies' => function ($query) {
$query->where('posts.approved', true)
->where('posts.is_starting_thread', false);
}])
->with(['posts' => function ($query) { // Posts
$query->approved()
->with('user') // Author of post
->latest();
}])
->with('user')
->paginate(20);