Rainier laan
Rainier laan

Reputation: 1130

Laravel 5.2 Foreach order by date

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

Answers (3)

Asur
Asur

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

Ru Chern Chong
Ru Chern Chong

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

Jerodev
Jerodev

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

Related Questions