← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

number_format() & money_format()

PHP PHP 4.0+ Beginner
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). No detection_hints.tools specified; PHPCS/Psalm won't flag missing formatting or non-locale-aware usage. money_format() removal in PHP 8 would be caught by a deprecation/compat scanner (e.g. PHPCompatibility) which is more like d5, but the broader misconception (locale-awareness) is only spotted in review or QA.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). Per quick_fix, swap echo $price for number_format($price, 2), or replace money_format() with NumberFormatter::formatCurrency(). It's slightly more than a one-line swap because money_format replacement requires constructing a NumberFormatter with a locale.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Formatting concerns live in the presentation layer; choosing number_format over NumberFormatter doesn't ripple through the architecture, though it does recur across many display sites.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception is explicit: developers assume number_format() respects locale (as similar functions in other languages do), but it doesn't. Combined with money_format() being removed in PHP 8 and silent string-to-float coercion losing precision, the 'obvious' usage contradicts expectations from other ecosystems.

About DEBT scoring →

Also Known As

number_format money_format PHP number formatting PHP currency format

TL;DR

number_format() formats a number with grouped thousands and a specified number of decimal places — the correct way to display prices, statistics, and large integers in PHP. money_format() was deprecated in PHP 7.4 and removed in PHP 8.0.

Explanation

number_format(float $num, int $decimals, string $decimal_separator, string $thousands_separator) converts a float to a formatted string. The defaults produce English-style formatting (1,234.56), but all separators are configurable for locale-specific output (1.234,56 for German). money_format() was a thin wrapper around the C library strfmon() — locale-dependent, not available on Windows, and removed in PHP 8.0. The modern replacement is NumberFormatter from the Intl extension, which handles currency symbols, locale rules, and sign conventions correctly. For simple price display without Intl, number_format() with explicit separators is safe and predictable.

Common Misconception

number_format() is locale-aware. It is not — it uses whatever separators you pass explicitly. For locale-correct output (currency symbols, right-to-left numbers, Arabic-Indic digits), use NumberFormatter from the Intl extension.

Why It Matters

Displaying raw floats to users (echo 1234.5) produces output missing thousands separators and trailing zeros — '1234.5' instead of '1,234.50'. number_format() is the one-liner fix. Knowing that money_format() was removed in PHP 8.0 prevents broken upgrades.

Common Mistakes

  • Using money_format() in code targeting PHP 8+ — it was removed; replace with NumberFormatter::formatCurrency() or number_format() with explicit separators.
  • Storing number_format() output in a database — it adds commas and periods that break numeric operations; always store raw numbers, format only for display.
  • Using number_format() for locale-sensitive output without configuring separators — the defaults are English-style regardless of server locale.
  • Passing a string to number_format() — it silently coerces to float, which can lose precision for large integers; use intl NumberFormatter for arbitrary precision.
  • Formatting floats for financial calculations — floats have precision errors; use bcmath or integer cents and format only at display time.

Code Examples

✗ Vulnerable
<?php
// ❌ Raw float output — no thousands separator, inconsistent decimals
$price = 1234.5;
echo $price;              // '1234.5' — missing separator, missing trailing zero
echo round($price, 2);   // '1234.5' — still no formatting

// ❌ money_format() — removed in PHP 8.0
echo money_format('%.2n', $price); // Fatal error on PHP 8+
✓ Fixed
<?php
// ✅ number_format() — simple, predictable
$price = 1234.5;
echo number_format($price, 2);            // '1,234.50'
echo number_format($price, 2, ',', '.');  // '1.234,50' — German style
echo '$' . number_format($price, 2);      // '$1,234.50'

// ✅ NumberFormatter (Intl) — locale-correct currency
$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1234.5, 'USD'); // '$1,234.50'

$fmt_de = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $fmt_de->formatCurrency(1234.5, 'EUR'); // '1.234,50 €'

Added 23 Mar 2026
Edited 18 Apr 2026
Views 49
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 1 ping T 0 pings F 1 ping S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 4 Google 4 Scrapy 4 ChatGPT 3 Ahrefs 3 Meta AI 2 Claude 2 PetalBot 2
crawler 27 crawler_json 4
DEV INTEL Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Replace echo $price with echo number_format($price, 2) for '1,234.50'. Replace any money_format() calls with NumberFormatter or number_format() with explicit separators.
📦 Applies To
PHP 4.0+ web cli
🔗 Prerequisites


✓ schema.org compliant