Multiple groupBy on Laravel Collection
Solution 1
The solution in https://stackoverflow.com/a/30469061/221745 can be improved on I think. The key is to remember that a grouped by collection is a collection of collections. Therefore, the following will work:
<?php
$recs = new \Illuminate\Database\Eloquent\Collection($query);
$grouped = $recs->groupBy('performed_at_year_month')->transform(function($item, $k) {
return $item->groupBy('performer_id');
});
Where $grouped
contains your final result
Solution 2
Laravel now (since 5.5.29) supports multi-level nested grouping, as per https://christoph-rumpel.com/2018/1/groupby-multiple-levels-in-laravel
$query = Activity::all()->groupBy(['performed_at_year_month', 'performer_id'])->toJson();
Solution 3
Instead of passing a string key, you may pass a callback. The callback should return the value you wish to key the group by:
$collection->groupBy(function($item, $key){
return $item["key-1"]."-".$item["key-2"];
});
Reference:- https://laravel.com/docs/5.7/collections#method-groupby
Solution 4
You can try chaining them, however I am not sure it will get you the results you want. May want to check to be sure
$query = Activity::all()->groupBy('performed_at_year_month')->groupBy('performer_id')->toJson();
I just checked this and you are correct, it's not preserving keys, although I think I can guess why. If a key happens to be the same, things will get overwritten. It could also be difficult to determine which key is what and overall feels a little "hacky" where there is likely a much better solution.
However, I think I've figured out how to do this.
$query = Activity::all();
$activities = new \Illuminate\Database\Eloquent\Collection($query);
$activities = $activities->groupBy('performed_at_year_month')->toArray() + $activities->groupBy('performer_id')->toArray();
echo json_encode($activities);
Related videos on Youtube
Michalis Antoniou
Updated on February 20, 2021Comments
-
Michalis Antoniou about 3 years
I am trying to group a collection by two clauses in Laravel 5, but it only groups it by the first one. Can someone please help me out? Here's my code.
$query = Activity::all()->groupBy('performed_at_year_month', 'performer_id')->toJson();
-
Michalis Antoniou almost 9 yearsThanks! This does return the data grouped correctly, but it does not include the keys (performed_at_year_month, performer_id) on the json string. Can you recommend a fix for that?
-
Clifton H. almost 6 yearsPass
true
as the second parameter forgroupBy($string, $preserveKeys)
.$activities->groupBy('performed_at_year_month', true)