Not sure I understand what you need, but I think you want each group index to be 0-based.
Problem is when you call:
$group = $prods->groupBy('product_id');
The resulting collection will be indexed by each group's product_id and not by 0-based increasing indices.
So when you call $group->each(function ($tot, $key) use ($products) { the $key will match each group's product_id.
If you want to reset those indices you can call ->values() after grouping them by:
// EDIT: added missing ->values() call
$group = $prods->groupBy('product_id')->values();
But, as a suggestion, I think you could simplify your code to:
// sample data
$prods = collect([
['product_id' => 1, 'product' => 'Product 1', 'quantity_client' => 11, 'quantity_seller' => 15],
['product_id' => 1, 'product' => 'Product 1', 'quantity_client' => 12, 'quantity_seller' => 16],
['product_id' => 1, 'product' => 'Product 1', 'quantity_client' => 13, 'quantity_seller' => 17],
['product_id' => 2, 'product' => 'Product 2', 'quantity_client' => 21, 'quantity_seller' => 25],
['product_id' => 2, 'product' => 'Product 2', 'quantity_client' => 22, 'quantity_seller' => 26],
['product_id' => 2, 'product' => 'Product 2', 'quantity_client' => 23, 'quantity_seller' => 27],
]);
$products = $prods
->groupBy('product_id')
->values() // reset groups' indices
->map(function ($group, $index) {
return [
'product_id' => $group[0]['product_id'],
'product' => $group[0]['product'],
'index' => $index,
'quantity_client' => $group->sum('quantity_client'),
'quantity_seller' => $group->sum('quantity_seller'),
];
});
return $products;
If you really think calling ->sum(...) twice is a no-go as it would iterate each group twice you can try using ->reduce(...)
$prods = collect([
['product_id' => 1, 'product' => 'Product 1', 'quantity_client' => 11, 'quantity_seller' => 15],
['product_id' => 1, 'product' => 'Product 1', 'quantity_client' => 12, 'quantity_seller' => 16],
['product_id' => 1, 'product' => 'Product 1', 'quantity_client' => 13, 'quantity_seller' => 17],
['product_id' => 2, 'product' => 'Product 2', 'quantity_client' => 21, 'quantity_seller' => 25],
['product_id' => 2, 'product' => 'Product 2', 'quantity_client' => 22, 'quantity_seller' => 26],
['product_id' => 2, 'product' => 'Product 2', 'quantity_client' => 23, 'quantity_seller' => 27],
]);
$products = $prods
->groupBy('product_id')
->values() // reset indices
->map(function ($group, $index) {
$values = $group->reduce(function ($values, $record) {
$values['quantity_client'] += $record['quantity_client'] ?? 0;
$values['quantity_seller'] += $record['quantity_seller'] ?? 0;
return $values;
}, ['quantity_client' => 0, 'quantity_seller' => 0]);
return [
'product_id' => $group[0]['product_id'],
'product' => $group[0]['product'],
'index' => $index,
'quantity_client' => $values['quantity_client'],
'quantity_seller' => $values['quantity_seller'],
];
});
return $products;
I personally don't think the performance impact is noticeable, unless you have a really huge dataset.
Hope it helps.