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

eggplantSword's avatar

Eloquent GroupBy where date >= today

How can I groupBy into two categories: active and inactive by checking the end_date to see if it's from yesterday or before?

The groups don't have to have those names just the active ones first and the inactive ones in the second group. However if there aren't any I still need an empty array so that this always has the same format (active first, inactive second)

$surveys = Survey::orderByDesc('created_at')
			->get()
			->groupBy(function ($item) {
				return $item['end_date'] >= Carbon::now()->format('Y-m-d');
			});

Right now this does create both groups but if there arent any active ones than there is only one group and not both as I want.

For example the result would be something like this

[
//active
   [
      { survey data },
      { survey data }, ...
   ],
//inactive
   [
      { survey data },
      { survey data }, ...
   ]
]

or

[
//active
   [],
//inactive
   [
      { survey data },
      { survey data }, ...
   ]
]

or 

[
//active
   [
      { survey data },
      { survey data }, ...
   ],
//inactive
   []
]

How can I get it to work?

0 likes
6 replies
Nakov's avatar

I think that this will help better: https://laravel.com/docs/8.x/collections#method-partition

[$active, $inactive] = Survey::orderByDesc('created_at')
			->get()
			->partition(function ($item) {
				if ($item['end_date'] && $item['end_date'] instanceof Carbon)
				{
					return $item['end_date']->gte(Carbon::now());
				}
	
				return false;
			});

dd($active->count(), $inactive->count());

I think that I improved your comparison of the date as well, because the way you compared it didn't make sense to me. You were comparing strings. So make sure you compare an instance of Carbon dates. In case $item['end_date'] is not Carbon instance you can make it using Carbon::createFromFormat('Y-m-d', $item['end_date']); for example.

eggplantSword's avatar

@Nakov this doesn't work as expected, all the surveys are in the inactive but only 3 should be inactive. I don't really see where you're checking if the end_date is greater or equal to today either

Nakov's avatar
Nakov
Best Answer
Level 73

@msslgomez I don't have your data to test, but this is where I check

return $item['end_date']->gte(Carbon::now());

I said you've got to make sure that the $item['end_date'] is an instance of Carbon, if it is not I gave you option on how to make it one. Then ->gte means great than or equal to.

Snapey's avatar

@Nakov if the partition is by all records prior today then use today() not now()

return $item['end_date']->gte(today());

true for all items that end > today at 00:00

Tray2's avatar

Something like this?

$today = Carbon::today()->format('Y-m-d'):

DB::select("SELECT 'inactive', *
FROM table
WHERE end_date >= ?
UNION ALL
SELECT 'active', *
FROM table
WHERE end_date <= ?", [$today, $today]);

Please or to participate in this conversation.