4

good day everyone

I'm new to Laravel and currently building my first simple news app with it

I have a simple query that using laravel's eager loading function But in this eager loading function, I want to fetch certain comments based on some conditions

Example:

use App\News;
...

public function home() {
    $news = News::with([
                    'thumbnail',
                    'source', // link to real news source
                    'comments' => function ($query) {
                        // fetch a comment where likes > 0, otherwise, get latest comment
                        // *get only one*
                    }
                ])->paginate(5);

    return response()->json([
        'news' => $news
    ]);
}

How to do this?

UPDATE

I found a way to order comments by likes count, but I do not know how to order them by 'created_at' (fetch latest comment) if there are no likes in each comment

I need to include 'likes_count' using withCount('likes') And then order them in by descending

public function home() {
    $news = News::with([
        'thumbnail',
        'source',
        'comments' => function ($query) {
            $query->withCount('likes');
            $query->orderBy('likes_count', 'DESC')->first();

            // return the first comment that has likes or most liked comment
        }
    ])->paginate(5);

    ...
}

Now how to put fallback query to order comments by 'created_at' (newest one) if there are no like in comments?

Thanks in advance

Gwein
  • 109
  • 3
  • 14
  • Add another order by created at desc so if all comments have 0 likes then the newest one will apprear first in list, same if comments have like then they are also sorted using created at – M Khalid Junaid Jan 31 '21 at 17:16
  • 1
    You were right, thanks for pointing it – Gwein Feb 01 '21 at 07:02
  • 1
    I have to put 2 query orderBy() One is likes_count, and other one is created_at `$query->orderBy('likes_count', 'DESC')->first();` `$query->orderBy('created_at', 'DESC')->first();` I have tested it by deleting and restoring likes on a comment multiple times And it's working And btw, are you going to answer my question? If you are, I will mark your answer as the correct one, otherwise I will answer it Again, thank you – Gwein Feb 01 '21 at 07:05

1 Answers1

3

Your current approach looks fine for ordering your results by likes count in case of no likes you can still get latest record by adding another order by clause with created_at column

$news = News::with([
    'thumbnail',
    'source',
    'comments' => function ($query) {
        $query->withCount('likes');
        $query->orderBy('likes_count', 'DESC')
              ->orderBy('created_at', 'DESC');
    }
])->paginate(5);

Copied from initial comment

So if all comments have 0 likes then the newest one will appear first in list, same if comments have likes then they are also sorted first with likes count and then with created at.

Once you have ordered collection then while you are looping your news records then pick the first item from your related records

M Khalid Junaid
  • 63,861
  • 10
  • 90
  • 118
  • 1
    Btw, I have a simple question Is there any differences between putting those queryBy together and separate them in 2 lines? – Gwein Feb 01 '21 at 07:25
  • 1
    @ChristianDelvianto No there isn;t much difference , doing in same line is basically called method chaining – M Khalid Junaid Feb 01 '21 at 07:27
  • @ChristianDelvianto I have updated my answer, using `First()` will return only one comment for one of the news so you need to load all comments sorted by like count/created at and while when your are showing news then pick first record from sorted comment collection, cheers – M Khalid Junaid Feb 01 '21 at 07:36