I’m trying to figure out the best way (whether I do this using the query builder or raw PHP) to get the most recent array item based on it’s created_at
timestamp for a given day, in an array containing many days.
For example…
[ [ "name" => "John", "created_at" => "2021-01-17 23:00:00" ], [ "name" => "Jane", "created_at" => "2021-01-17 20:00:00" ], [ "name" => "Edward", "created_at" => "2021-01-16 19:00:00" ], [ "name" => "Scott", "created_at" => "2021-01-16 17:00:00" ] ]
In the above I have two days, each day has an entry and I’d like to get the newest one for each of the days, e.g:
[ [ "name" => "John", "created_at" => "2021-01-17 23:00:00" ], [ "name" => "Edward", "created_at" => "2021-01-16 19:00:00" ] ]
I currently have a query that gets everything between two dates…
$events = GoogleAnalytics::where('event_category', $category) ->where('event_action', $action) ->whereDate('period_from', '>=', $from) ->whereDate('period_to', '<=', $to) ->orderBy('created_at', 'desc') ->get();
Advertisement
Answer
Using laravel collections helper you can pick latest record for each day first sort collection, then group your collection by day i.e grouping criteria and then using map pick first result from each group
$collection = $collection->sortByDesc('created_at'); $results = $collection->groupBy(function ($item, $key) { $date= new DateTime($item['created_at']); return $date->format('Y-m-d'); }); $results = $results->map(function ($item, $key) { return $item[0]; });
Result set will look like as
Array ( [2021-01-17] => Array ( [name] => John [created_at] => 2021-01-17 23:00:00 ) [2021-01-16] => Array ( [name] => Edward [created_at] => 2021-01-16 19:00:00 ) )
Or another shorter version would be group , map + sort
$results = $collection->groupBy(function ($item, $key) { $date= new DateTime($item['created_at']); return $date->format('Y-m-d'); }); $results = $results->map(function ($item, $key) { return $item->sortByDesc('created_at')->first(); });