Home > Software design >  Laravel - sort array from other class by SQL table column
Laravel - sort array from other class by SQL table column

Time:12-03

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?

CodePudding user response:

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

CodePudding user response:

$poll->comments->sortBy('likes')
  • Related