Reputation: 1130
I made a view that shows a Post and the replies to that post. As of this question, the replies are in a foreach loop and in random order. Is there a way to order the foreach loop so that the earliest reply is at the top? and the oldest reply at the bottom?.
This the the loop
@foreach($topic->replies as $reply)
<div class="collection">
<div class="collection-item row">
<div class="col s3">
<div href="" class="avatar collection-link">
<div class="row">
<div class="col s3"><img src="/uploads/avatars/{{ $reply->user->avatar }}" alt="" class="circle" style="width: 50px;"></div>
<div class="col s9">
<p class="user-name">{{ $reply->user->username }}</p>
</div>
</div>
<p>Role: {{ $reply->user->role->role_name }}</p>
<p>Since: {{ $reply->user->created_at }}</p>
<p class="post-timestamp">Posted on: {{ $reply->created_at }}</p>
</div>
</div>
<div class="col s9">
<div class="row last-row">
<div class="col s12">
<p>{!! $reply->reply_text !!}</p>
</div>
</div>
<div class="row last-row block-timestamp">
<div class="col s6">
<p class="post-timestamp">Last changed: {{ $reply->updated_at }}</p>
</div>
</div>
</div>
</div>
</div>
@endforeach
TopicsController.php (Show method)
public function show($theme_id, $topic_id)
{
$theme = Theme::with('topics')->findOrFail($theme_id);
$topic = Topic::with('theme')->findOrFail($topic_id);
return view('topics.topic')->withTopic($topic)->withTheme($theme);
}
Thanks in advance!
Upvotes: 1
Views: 5513
Reputation: 4017
For me the cleanest option is, in your Topic
model, order the relations results by default using the created_at
timestamp like this:
class Topic
{
public function replies()
{
return $this->hasMany('Reply')->orderBy('created_at','desc');
}
}
This way you don't need to order the collection afterwards, and let the sql do the work, resulting in a lighter code and better performance since you almost every time will need the Topics ordered that way.
This also has the advantage that the code you shared can remain untouched, but I would recommend you to eager load the relation in your controller (to avoid unnecessary queries from being performed):
$topic = Topic::with(['theme','replies'])->findOrFail($topic_id);
Hope this helps you.
Upvotes: 0
Reputation: 3756
public function show($theme_id, $topic_id)
{
$theme = Theme::with([
'topics' => function($query) {
$query->orderBy('replies');
}
])->findOrFail($theme_id);
$topic = Topic::with('theme')->findOrFail($topic_id);
return view('topics.topic')->withTopic($topic)->withTheme($theme);
}
https://laravel.com/docs/5.4/eloquent-relationships#constraining-eager-loads
Upvotes: 1
Reputation: 33186
All Eloquent queries return Laravel collections. So you can use the sortBy
function to order your replies in the foreach.
@foreach($topic->replies->sortByDesc('created_at') as $reply)
However, a better solution would be to order your replies in the query. This can be achieved by updating your Eloquent query like this:
$topic = Topic::with([
'theme',
'replies' => function ($query) {
$query->orderByDesc('created_at');
}
])
->findOrFail($topic_id);
Upvotes: 5