skip to Main Content

I am calling an array of all the comments of a poll by using the following code:

$poll = Poll::find($id);
      return view('pages.poll', ['poll' => $poll, 'comments' => $poll->comments]);

and the links between Comments and Polls are the following:

Comment.php

public function poll() {
    return $this->belongsTo(Poll::class, 'poll_id');
}

Poll.php

public function comments() {
    return $this->hasMany(Comment::class, 'poll_id');
}

Finally, I would like to sort the array comments coming from $poll->comment by the column likes in the Comment table, something like DB::table('comment')->orderBy('likes')->get();.

Is there any way to do that?

2

Answers


  1. $poll->comments->sortBy('likes')
    
    Login or Signup to reply.
  2. There’s a number of ways you can do this.

    1. Add orderBy('likes') directly to your comments relationship:

    Poll.php:

    public function comments() {
      return $this->hasMany(Comment::class, 'poll_id')->orderBy('likes');
    }
    

    Now, any time you access $poll->comments, they will be automatically sorted by the likes column. This is useful if you always want comments in this order (and it can still be overridden using the approaches below)

    1. "Eager Load" comments with the correct order:

    In your Controller:

    $poll = Poll::with(['comments' => function ($query) {
      return $query->orderBy('likes');
    })->find($id);
    
    return view('pages.poll', [
      'poll' => $poll,
      'comments' => $poll->comments
    ]);
    

    with(['comments' => function ($query) { ... }]) adjusts the subquery used to load comments and applies the ordering for this instance only. Note: Eager Loading for a single record generally isn’t necessary, but can be useful as you don’t need to define an extra variable, don’t need to use load, etc.

    1. Manually Load comments with the correct order:

    In your Controller:

    $poll = Poll::find($id);
    $comments = $poll->comments()->orderBy('likes')->get();
    
    return view('pages.poll', [
      'poll' => $poll,
      'comments' => $comments
    ]);
    

    Similar to eager loading, but assigned to its own variable.

    1. Use sortBy('likes'):

    In your Controller:

    $poll = Poll::find($id);
    
    return view('pages.poll', [
      'poll' => $poll,
      'comments' => $poll->comments->sortBy('likes')
    ]);
    

    Similar to the above approaches, but uses PHP’s sorting instead of database-level sorting, which can be significantly less efficient depending on the number of rows.

    https://laravel.com/docs/9.x/eloquent-relationships#eager-loading

    https://laravel.com/docs/9.x/eloquent-relationships#constraining-eager-loads

    https://laravel.com/docs/9.x/collections#method-sortby

    https://laravel.com/docs/9.x/collections#method-sortbydesc

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search