php - order groupBy method by total and get also all rows in laravel
I want to order my products like this, get all products, group them by color, and get first three color with most item.
$products = Products::select('color', DB::raw('count(*) as total'))
->groupBy('color')
->orderBy('total', 'desc')
->limit(3)
->get();
but it only gives me something like this:
[
{
"color": "red",
"total": 3
},
{
"color": "blue",
"total": 2
},
{
"color": "yellow",
"total": 1
}
]
with no total, It gives me all rows grouped by color, but I want to get all rows grouped by color and order them with total.
something like this order by each total: (red color comes, then blue and yellow)
{
"red": [
{
"id": 1,
"title": "first red product",
"color": "red",
"created_at": "2022-09-03T23:44:59.000000Z",
"updated_at": "2022-09-03T23:44:59.000000Z"
},
{
"id": 3,
"title": "second red product",
"color": "red",
"created_at": "2022-09-03T23:45:40.000000Z",
"updated_at": "2022-09-03T23:45:40.000000Z"
},
{
"id": 6,
"title": "some red product",
"color": "red",
"created_at": "2022-09-03T23:44:59.000000Z",
"updated_at": "2022-09-03T23:44:59.000000Z"
}
],
"blue": [
{
"id": 2,
"title": "some blue product",
"color": "blue",
"created_at": "2022-09-03T23:45:40.000000Z",
"updated_at": "2022-09-03T23:45:40.000000Z"
},
{
"id": 4,
"title": "another blue product",
"color": "blue",
"created_at": "2022-09-03T23:45:40.000000Z",
"updated_at": "2022-09-03T23:45:40.000000Z"
}
],
"yellow": [
{
"id": 5,
"title": "some yellow product",
"color": "yellow",
"created_at": "2022-09-03T23:45:40.000000Z",
"updated_at": "2022-09-03T23:45:40.000000Z"
}
]
}
Answer
Solution:
You can use collection method: groupBy
sortBy
count
map
take
all
$products = Products::all()
->groupBy('color')
->sortBy(fn ($groupValue, $groupKey) => count($groupValue), SORT_REGULAR, true)
->map(fn($groupValue, $groupKey) => $groupValue->take(3))
->all();
Source