按最新(最新)相关型号订购[Laravel]

时间:2017-12-25 04:36:04

标签: php sql laravel laravel-5 laravel-eloquent

我正在使用Laravel 5.4,我有以下关系:

  • 论坛hasMany主题(threads()
  • 帖子hasMany发布(posts()
  • 主题belongsTo用户(user()
  • 发布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应该会显示主题的列表,其中每个主题将会出现:

  • 其作者(这就是为什么我有->with('user')
  • 回复数量(这就是为什么我有>withCount(['posts AS approved_replies' => function ($query) { ...
  • 最新(最新)帖子及其作者的日期。这就是原因:

        ->with(['posts' => function ($query) { // Posts
            $query->approved()
                ->with('user') // Author of post
                ->latest(); // LATEST first
            }]
        )
    

    ...因为在index.blade.php我可以通过以下方式访问每个帖子的最新帖子:

    @foreach ($threads as $thread) 
        {{ $thread->posts->first()->created_at; }}
        {{ $thread->posts->first()->user->username; }}
    @endforeach 
    

此代码的问题是线程按其created_at排序,而不是最近的帖子。我想要实现的是通过最新的(最新的)帖子订购线程,但我不知道如何做到这一点。

2 个答案:

答案 0 :(得分:4)

以下是我的表现。它不是特别漂亮,但应该做的工作

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

答案 1 :(得分:0)

您需要使用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);