Was macht PHP array_reduce()?
Wer in PHP eine Liste von Daten zu einem einzigen Endergebnis verdichten möchte, sei es eine Summe, ein Produkt oder ein gruppiertes Statistik-Objekt, der trifft früher oder später auf PHP array_reduce. Die Funktion läuft über jedes Element eines Arrays, ruft einen Callback auf und reicht den jeweils aktuellen Zwischenstand an die nächste Iteration weiter. Am Ende bleibt ein einziger Wert übrig, der das gesamte Array repräsentiert.

Vom einfachen Summen-Beispiel bis zum Group-By-Pattern zeigt sich gleich, warum der Akkumulator-Gedanke für sauberen funktionalen Code so nützlich ist.
Genau diese Eigenschaft macht PHP array_reduce zu einem zentralen Baustein des funktionalen Programmierstils. Im Vergleich zu einer foreach-Schleife mit manuellem Akkumulator ist der Aufruf kompakter und macht die Absicht des Codes besser sichtbar. In diesem Tutorial geht es Schritt für Schritt vom einfachen Summen-Beispiel bis zum Group-By-Pattern mit assoziativem Akkumulator.
Syntax und Callback-Signatur
Die Signatur ist knapp gehalten und besteht aus drei Parametern. PHP array_reduce erwartet das zu reduzierende Array, einen Callback und optional einen Initialwert.
<?php
array_reduce(array $array, callable $callback, mixed $initial = null): mixed
Der Callback bekommt zwei Argumente. Das erste, oft $carry genannt, trägt den aktuellen Zwischenstand. Das zweite, $item, ist das Element, das gerade verarbeitet wird. Der Rückgabewert des Callbacks wird zum neuen $carry der nächsten Iteration. Der dritte Parameter $initial gibt den Startwert vor und wird beim ersten Aufruf als $carry übergeben. Beim Aufruf eines leeren Arrays ohne Initialwert liefert die Funktion null zurück, was bei numerischen Operationen oft zu unerwarteten Ergebnissen führt.
Einfache Aggregation: Summe und Produkt
Der häufigste Einstieg ist die klassische Summe. Sie lässt sich in einer einzigen Zeile ausdrücken und macht den Akkumulator-Gedanken greifbar.
<?php
$preise = [9.95, 14.50, 19.00];
$summe = array_reduce($preise, fn($carry, $item) => $carry + $item, 0);
echo $summe;
/* 43.45 */
Soll statt summiert multipliziert werden, ändert sich nur der Operator und der Initialwert. Wichtig ist, dass die Multiplikation mit 1 startet, sonst ist das Ergebnis immer 0.
<?php
$werte = [2, 4, 5];
$produkt = array_reduce($werte, fn($carry, $item) => $carry * $item, 1);
echo $produkt;
/* 40 */
Wer ausschließlich numerische Werte aus einem flachen Array zusammenrechnen möchte, kann auch direkt zu array_sum() greifen. Sobald aber Bedingungen, Filterungen oder Multi-Wert-Ergebnisse ins Spiel kommen, spielt PHP array_reduce seine Stärken aus.
Mehrere Statistik-Werte in einem Pass berechnen
Reporting-Module müssen oft Min, Max und Summe gleichzeitig liefern. Drei separate Aufrufe von Aggregat-Funktionen würden das Array dreimal durchlaufen. Mit PHP array_reduce und einem assoziativen $carry-Array geschieht das in einem einzigen Pass.
<?php
$werte = [12, 7, 25, 9, 18];
$stats = array_reduce($werte, function ($carry, $item) {
$carry['min'] = min($carry['min'], $item);
$carry['max'] = max($carry['max'], $item);
$carry['summe'] += $item;
return $carry;
}, ['min' => PHP_INT_MAX, 'max' => PHP_INT_MIN, 'summe' => 0]);
print_r($stats);
/* Array ( [min] => 7 [max] => 25 [summe] => 71 ) */
Der Initialwert ist hier ein vordefiniertes Array. So kann der Callback im ersten Durchlauf ohne Sonderbehandlung auf alle drei Schlüssel zugreifen. Die Sentinel-Werte PHP_INT_MAX und PHP_INT_MIN sorgen dafür, dass das erste Element zuverlässig die Initialwerte überschreibt.
Strings mit Bedingung joinen
Manchmal soll ein Array zu einem einzelnen String zusammengefasst werden, dabei aber leere Einträge übersprungen werden. Reines implode() kann das nicht. Mit PHP array_reduce ist die Logik in einer Funktion vereint.
<?php
$tags = ['php', '', 'array', 'reduce', ''];
$liste = array_reduce($tags, function ($carry, $item) {
$item = trim($item);
if ($item === '') {
return $carry;
}
return $carry === '' ? $item : $carry . ', ' . $item;
}, '');
echo $liste;
/* php, array, reduce */
Die Prüfung auf $carry === '' verhindert ein führendes Komma, das sonst beim ersten Element entstehen würde. Wer das Filter-Verhalten häufiger braucht, kombiniert vorher array_filter() mit implode() und kommt ebenfalls schnell zum Ziel.
Group-By mit array_reduce()
Eines der mächtigsten Muster ist Group-By: Einträge werden nach einem Schlüssel gruppiert und pro Gruppe wird ein Wert akkumuliert. Typischer Anwendungsfall sind Bestellungen pro Kunde oder Logzeilen pro Statuscode.
<?php
$bestellungen = [
['kunde' => 'A', 'betrag' => 19.90],
['kunde' => 'B', 'betrag' => 49.00],
['kunde' => 'A', 'betrag' => 14.50],
];
$summen = array_reduce($bestellungen, function ($carry, $item) {
$kunde = $item['kunde'];
$carry[$kunde] = ($carry[$kunde] ?? 0) + $item['betrag'];
return $carry;
}, []);
print_r($summen);
/* Array ( [A] => 34.4 [B] => 49 ) */
Der null-Coalescing-Operator ?? macht den Code besonders kompakt: Wenn der Schlüssel im Akkumulator noch nicht existiert, wird 0 als Startwert genutzt. Ein Hinweis zur Lesbarkeit dieses Operators steht im Tutorial zum Null-Coalescing-Operator.
flowchart TD
A["Start: initial wird carry"] --> B["Erstes Item aus Array"]
B --> C["Callback: neuer carry = f(carry, item)"]
C --> D{"Weitere Items?"}
D -->|Ja| B
D -->|Nein| E["Endwert zurueckgeben"]
array_reduce() vs array_map und array_filter
Die drei Funktionen werden oft in einem Atemzug genannt, machen aber sehr unterschiedliche Dinge. array_map() ist eine 1:1-Transformation, jedes Element wird durch den Callback ersetzt. array_filter() ist eine n:m-Auswahl, der Callback entscheidet, welche Elemente übernommen werden. PHP array_reduce ist eine n:1-Operation, am Ende bleibt ein einzelner Wert.
In größeren Code-Basen tritt oft eine Pipeline auf: Zuerst werden Daten transformiert, dann gefiltert, dann aggregiert. Verschachtelte Aufrufe wie array_reduce(array_filter(array_map($daten, $f), $g), $h, 0) sind zwar möglich, leiden aber schnell an Lesbarkeit. Ab einer gewissen Komplexität lohnt es sich, jede Stufe in eine eigene Variable mit sprechendem Namen zu legen oder direkt eine kleine Helper-Klasse zu bauen.
Wann foreach die bessere Wahl bleibt
PHP array_reduce ist deklarativ, foreach ist imperativ. Beides hat seine Berechtigung. Wer Schleifen mit break oder continue braucht, wer komplexe Bedingungen einbaut oder wer eine ungebremste Performance in heißen Code-Pfaden erreichen will, ist mit foreach besser bedient. Der Funktionsaufruf-Overhead pro Iteration fällt bei Millionen Einträgen ins Gewicht.
Für Anwendungs-Code in Reporting, Statistik oder Daten-Aggregation gewinnt PHP array_reduce dagegen meist beim Code-Review. Der Aufruf macht die Absicht sofort klar, ohne dass der Leser eine Schleife im Kopf nachvollziehen muss. Eine gute Faustregel: Wenn der Akkumulator nur aus einer Zuweisung pro Iteration besteht, ist array_reduce klarer. Wenn die Logik im Schleifenrumpf mehrere Verzweigungen enthält, ist foreach lesbarer.
Ein letzter Punkt für fortgeschrittene Nutzer: PHP array_reduce kennt keinen Early-Exit. Wer beim ersten Treffer abbrechen möchte, etwa bei der Suche nach einem bestimmten Element, sollte stattdessen array_find() seit PHP 8.4 nutzen oder einen klassischen foreach-Loop mit break einsetzen.
Performance-Faustregel: Faktor 10x bis 1000x langsamer als foreach
Ein Punkt, der in der Praxis oft unterschätzt wird: Der Performance-Unterschied zwischen array_reduce und foreach ist nicht "ein bisschen", sondern dramatisch. Bei einer simplen Summen-Aggregation über Millionen Werte ist foreach gut Faktor 10x schneller, bei kleineren Callbacks mit nur einer Operation pro Iteration sogar bis Faktor 1000x. Der Grund liegt nicht in array_reduce selbst (die Funktion ist in C implementiert), sondern im Userland-Callback: Pro Element entsteht der volle Overhead eines PHP-Funktionsaufrufs (Stack-Frame, Argument-Binding, Rückgabewert), der bei foreach komplett entfällt.
<?php
$werte = range(1, 1_000_000);
/* langsam: Funktionsaufruf pro Iteration */
$summe = array_reduce($werte, fn($c, $v) => $c + $v, 0);
/* deutlich schneller: kein Callback, nur Inline-Addition */
$summe = 0;
foreach ($werte as $v) {
$summe += $v;
}
/* fuer reine Summen ohnehin am schnellsten */
$summe = array_sum($werte);
Die Faustregel für Hot-Paths ist deshalb klar: In Schleifen, die pro Request millionenfach durchlaufen werden, etwa bei der Verarbeitung großer CSV-Importe, Log-Auswertungen oder Massendaten aus der Datenbank, gehört foreach hin. Für reine Summen oder Produkte ist array_sum() oder array_product() sogar nochmal eine Stufe schneller, weil der Callback komplett entfällt. array_reduce bleibt der richtige Griff für komplexere Aggregationen mit assoziativem Akkumulator (Group-By, Multi-Wert-Stats), wo Lesbarkeit und Wartbarkeit den minimalen Overhead pro Iteration deutlich aufwiegen.
Fazit
PHP array_reduce ist ein vielseitiges Werkzeug für alle Aufgaben, bei denen aus vielen Werten ein einzelner Wert oder ein zusammengefasstes Objekt entstehen soll. Wer die Callback-Signatur mit $carry und $item verstanden hat und den Initialwert bewusst setzt, kann Summen, Produkte, Min/Max-Statistiken, String-Joins und Group-By-Strukturen in wenigen Zeilen ausdrücken. Im Zusammenspiel mit array_map und array_filter entsteht ein klarer funktionaler Stil. Für Hot-Path-Schleifen oder Logik mit Early-Exit bleibt foreach die richtige Wahl, für alles andere ist PHP array_reduce ein Gewinn an Klarheit im Alltag.