Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

abhimanyusharma003's avatar

Group posts by date

I want to group posts by each day and order them like a calendar for creating a blog archive.

If I use this

Post::all()->groupBy(function($date) {
        return \Carbon\Carbon::parse($date->created_at)->format('d-M-y');
    });

I get output something like this, for sure posts are grouped according to dates, but dates itself are not properly ordered like calander, they are random.

Current output Random order of dates

Alt text

Expeted output Dates are properly ordered from current date to older dates

Example https://laravel-news.com/archive/

0 likes
12 replies
RachidLaasri's avatar

Well, i don't see any "orderBy" in your code, maybe something like :

Post::all()->groupBy(function($date) {
        return \Carbon\Carbon::parse($date->created_at)->format('d-M-y');
    })->orderBy('created_at');
2 likes
abhimanyusharma003's avatar

@RachidLaasri I want to order posts by dates of months by grouping them. Like here https://laravel-news.com/archive/

On December 2014 you have 6 posts then on November 2014 you have 5 posts and so on. ( Here grouping is done by months, I want to group by dates )

I can't use orderBy() on a collection, it throws error.

Please if you any other suggestion let me know.

pmall's avatar
pmall
Best Answer
Level 56

First of all created_at is already returned as a carbon object. This should work :

$posts = Post::all()->groupBy(function($item){ return $item->created_at->format('d-M-y'); });

Then use uksort to sort the array by keys using a cmp callback :

uksort($posts, function($a, $b)
{
  $ta = \Carbon\Carbon::parse($a)->timestamp;
  $tb = \Carbon\Carbon::parse($b)->timestamp;

  return $ta - $tb; // or $tb - $ta depending on the order you want
})

I don't know Carbon much so maybe Im wrong with its usage but I guess you get the idea.


Or else you can sort them first

$posts = Post::latest()->get()->groupBy(function($item)
{
  return $item->created_at->format('d-M-y');
});

I think it is cleaner.

6 likes
abhimanyusharma003's avatar

@pmall Many thanks for this :)

You missed ->toArray(); in the end.

$posts = Post::all()->groupBy(function($item){ return $item->created_at->format('d-M-y'); })->toArray();
pmall's avatar

I updated my answer with a cleaner solution. And I think you can directly throw a collection in uksort but not sure.

1 like
abhimanyusharma003's avatar

+1 to second solution this is just awesome. I tried the first one but uksort give error that expects parameter to be array, object given. After using ->toArray(); it works perfectly well.

tsurrette's avatar

+1 again to the clean solution from pmall. Thank you!

arvind3's avatar

Group posts by date $posts = Post::latest()->get() ->groupBy(DB::raw("DATE(created_at)"));

anas-k's avatar

@PMALL - thanks a lot, I searched for this code for 2 and half hours, until I found your answer.

Please or to participate in this conversation.