Beträge und Zahlen in PHP formatieren – number_format, sprintf und Intl
1234.5 ist keine Anzeige, sondern ein Wert. Auf der Rechnung soll 1.234,50 € stehen, in der API 1234.50 und im Dateinamen 1234-50. Drei Aufgaben, drei Werkzeuge – und ein Fehler, den fast jeder einmal macht.
Deutsche Zahlen haben Punkt und Komma genau andersherum als englische. Das klingt banal, ist aber die Quelle einer ganzen Fehlerfamilie: falsch angezeigte Rechnungen, Beträge, die beim Import um den Faktor 1000 danebenliegen, Summen mit drei Nachkommastellen.
Der Standardfall: number_format
$betrag = 1234.5;
number_format($betrag, 2, ',', '.'); // 1.234,50
number_format($betrag, 2, ',', '.') . ' €'; // 1.234,50 €
number_format(0.5, 1, ',', '.'); // 0,5
number_format(1234567, 0, ',', '.'); // 1.234.567Die vier Parameter sind: Wert, Nachkommastellen, Dezimaltrennzeichen, Tausendertrennzeichen. Merksatz für Deutschland: Komma trennt die Stellen, Punkt gruppiert die Tausender.
Wenn es exakt sein muss: sprintf
sprintf('%0.2f', 1234.5); // 1234.50 – für APIs und CSV
sprintf('%05d', 42); // 00042 – führende Nullen, z. B. Rechnungsnummern
sprintf('%+.1f %%', 12.345); // +12.3 % – mit Vorzeichen
sprintf('RE-%04d-%s', 7, '2026') // RE-0007-2026%f benutzt immer den Punkt – genau richtig für Schnittstellen, in denen eine Zahl eine Zahl bleiben soll.
Mehrsprachig: die Intl-Erweiterung
$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
$fmt->formatCurrency(1234.5, 'EUR'); // 1.234,50 €
$en = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$en->formatCurrency(1234.5, 'EUR'); // €1,234.50
$prozent = new NumberFormatter('de_DE', NumberFormatter::PERCENT);
$prozent->format(0.1925); // 19 %NumberFormatter kennt die Regeln je Sprache – Position des Währungszeichens, geschütztes Leerzeichen, Gruppierung. Der Haken: Die Erweiterung intl muss auf dem Server aktiv sein. Prüfe das einmal mit extension_loaded('intl') und halte für den Fall der Fälle number_format als Rückfalllösung bereit.
Geld nicht als Fließkommazahl rechnen
0.1 + 0.2 === 0.3; // falseDas ist kein PHP-Problem, sondern Binärarithmetik. Für Beträge, die addiert und verglichen werden, rechne in Cent als Integer:
$netto = 19999; // 199,99 €
$steuer = (int)round($netto * 0.19); // 3800
$brutto = $netto + $steuer; // 23799
echo number_format($brutto / 100, 2, ',', '.') . ' €'; // 237,99 €Erst ganz am Ende, für die Anzeige, wird geteilt.
Fallstrick
Eingaben zurückzulesen ist die andere Hälfte der Aufgabe: (float)"1.234,50" ergibt 1.234, nicht 1234,50 – PHP hört beim Komma auf. Aus einem Formular kommt der Wert deshalb erst durch eine Normalisierung:
$roh = '1.234,50';
$wert = (float)str_replace(',', '.', str_replace('.', '', $roh)); // 1234.5Und speichere Zahlen nie formatiert in der Datenbank. In die Spalte gehört der Wert, die Darstellung entsteht bei der Ausgabe.
Rechnungen, Auswertungen und Exporte, bei denen die Zahlen stimmen, baue ich regelmäßig – schreib mir über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Benannte Argumente in PHP 8 – Schluss mit true, false, null, true
Ein Aufruf wie erstelle($a, true, false, null, true) sagt nichts darüber, was die Wahrheitswerte bedeuten. Mit benannten Argumenten steht es im Aufruf – und optionale Parameter lassen sich überspringen.
Reguläre Ausdrücke in PHP – benannte Gruppen statt $m[3]
Ein Treffer-Array aus Zahlen liest sich nach zwei Wochen wie eine Geheimschrift. Benannte Gruppen geben jedem Teil einen Namen – und preg_replace_callback ersetzt damit Dinge, die kein einfacher Ersetzungsstring kann.
json_decode mit JSON_THROW_ON_ERROR – Fehler, die man nicht übersehen kann
Kaputtes JSON gibt bei json_decode ein stilles null zurück – dasselbe null, das auch im gültigen JSON stehen kann. Ein Flag macht daraus eine Ausnahme, und aus der Fehlersuche wird eine Zeile Stacktrace.