array_sum() and array_product() cover plain totals. array_reduce($a, $fn, $initial) calls $fn($carry, $item) for each element, passing each result on as the next carry. Give the initial value explicitly, since it defaults to null: 0.0 for money, [] for a grouping.
<?php
set_error_handler(fn(int $no, string $msg) => print "Warning: $msg\n");
$items = [['cat' => 'SF', 'qty' => 2, 'price' => 9.99], ['cat' => 'Classic', 'qty' => 1,
'price' => 4.5], ['cat' => 'SF', 'qty' => 3, 'price' => 12.0]];
$total = array_reduce($items, fn(float $sum, array $i) => $sum + $i['qty'] * $i['price'], 0.0);
echo array_sum(array_column($items, 'qty')), ' ', number_format($total, 2), "\n";
$byCat = array_reduce($items, function (array $acc, array $i): array {
$acc[$i['cat']] = ($acc[$i['cat']] ?? 0) + $i['qty']; // group and count
return $acc;
}, []);
echo json_encode($byCat), ' ', $items |> (fn($x) => array_column($x, 'price')) |> max(...);
echo "\n", array_sum([10, '5', [1]]), "\n"; // PHP 8.3: warnsOutput
6 60.48
{"SF":5,"Classic":1} 12
Warning: array_sum(): Addition is not supported on type array
15The grouping reducer mirrors GROUP BY (GROUP BY, HAVING, and ROLLUP), which is better done in MySQL 524 while the rows are still there. The PHP 8.5 pipe |> (The Pipe Operator) chains steps left to right. Since PHP 8.3, array_sum() and array_product() behave like a loop with + and *, so an array in the input raises the warning shown and is skipped; older versions skipped it silently.