money_format
Formatted a number as a locale-aware currency string; removed in PHP 8.0.
money_format(string $format, float $number): string- Added in PHP 4.3.0
- Deprecated since PHP 7.4.0
- Removed in PHP 8.0.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$format | string | A strfmon(3) format specification: a % character, optional flags, field width, left precision, right precision, and a required conversion character (i, n or %). |
$number | float | The number to format. |
Return value
stringThe formatted currency string. Text before and after the conversion specification is returned unchanged.
Errors
On PHP 8.0 and later the function does not exist, so calling it raises a fatal Error: Call to undefined function money_format().
Changelog
- PHP 8.0.0Removed. Use NumberFormatter::formatCurrency() from the intl extension instead.
- PHP 7.4.0Deprecated.
money_format() wrapped the C library's strfmon() and formatted a single number according to the LC_MONETARY locale — inserting the right currency symbol, thousands separator and decimal mark for the locale set by setlocale(). It was deprecated in PHP 7.4 and removed in PHP 8.0. On any supported PHP version today, calling it is a fatal error.
What to use instead
Use NumberFormatter::formatCurrency() from the intl extension. It takes an explicit locale and an explicit ISO 4217 currency code, which is strictly better than the old function: money_format() could only ever produce the currency of the process-wide locale, so formatting a euro amount for a US visitor was impossible without switching locales globally.
$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1234.56, 'EUR');Why it was removed
It was never available on Windows, because Windows has no strfmon(). It depended on a global locale setting that is not thread-safe and that any library could change underneath you. And its format specifiers were obscure C conventions rather than anything PHP-like. If intl is unavailable, number_format() plus a hardcoded symbol is a workable, if unlocalised, fallback.
Example
<?php
// PHP 7.3 and earlier only — removed in PHP 8.0.
setlocale(LC_MONETARY, 'en_US.UTF-8');
echo money_format('%.2n', 1234.56), "\n"; // $1,234.56
echo money_format('%.2n', -1234.56), "\n"; // -$1,234.56
echo money_format('%(.2n', -1234.56), "\n"; // ($1,234.56)
echo money_format('%=*(#10.2n', -1234.5672), "\n"; // ($********1,234.57)
setlocale(LC_MONETARY, 'de_DE.UTF-8');
echo money_format('%.2n', 1234.56), "\n"; // 1.234,56 EURWhen to use it
- Reading legacy PHP 5 or 7 code and understanding what a %.2n format string produced.
- Migrating an older codebase to NumberFormatter::formatCurrency() during a PHP 8 upgrade.
- Choosing a fallback when the intl extension is not installed on the target server.
Frequently asked questions
Why does money_format give an undefined function error?
Because it was removed in PHP 8.0 after being deprecated in 7.4. On PHP 8 and later the function simply does not exist, so any call raises a fatal Error. Replace it with NumberFormatter::formatCurrency().
What is the replacement for money_format in PHP 8?
NumberFormatter::formatCurrency() from the intl extension. It takes an explicit locale and ISO 4217 currency code, so it can format any currency for any locale without changing a global setting.
How do I format currency without the intl extension?
Use number_format() with your chosen decimal and thousands separators and concatenate the symbol yourself. The output will not be localised, so this only works when you serve one market.
More examples
The modern replacement: NumberFormatter
Locale and currency are separate arguments, so the same amount can be shown as euros to a German visitor and as dollars to an American one without touching a global setting. The formatter also places the symbol, separators and minus sign according to each locale's rules — note that de_DE puts the symbol after the number. This requires the intl extension, which is bundled with PHP but not always enabled.
<?php
$us = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $us->formatCurrency(1234.56, 'USD'), "\n"; // $1,234.56
echo $us->formatCurrency(1234.56, 'EUR'), "\n"; // €1,234.56
$de = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $de->formatCurrency(1234.56, 'EUR'), "\n"; // 1.234,56 €
echo $de->formatCurrency(-99.5, 'USD'), "\n"; // -99,50 $Mapping old format strings to the new API
The old conversion characters map onto formatter configuration rather than format strings: n was the local symbol, i the international currency code, and the ! flag suppressed the symbol entirely. Rebuilding that last case means using a DECIMAL formatter with a two-digit minimum fraction, since a CURRENCY formatter always emits a symbol.
<?php
$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
// money_format('%.2n', $n) -> local currency symbol
echo $fmt->formatCurrency(1234.5, 'USD'), "\n";
// money_format('%.2i', $n) -> international code
$intl = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$intl->setTextAttribute(NumberFormatter::CURRENCY_CODE, 'USD');
echo $intl->formatCurrency(1234.5, 'USD'), "\n";
// money_format('%!.2n', $n) -> suppress the symbol
$plain = new NumberFormatter('en_US', NumberFormatter::DECIMAL);
$plain->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, 2);
echo $plain->format(1234.5), "\n";Fallback when intl is not installed
number_format() plus an explicit symbol reproduces the common English-locale output without any extension. It is not localised — the separators and symbol placement are hardcoded — so use it only when you serve a single known market, or when intl genuinely cannot be installed. Handling the sign before the symbol avoids the "$-1,234.50" mistake.
<?php
function formatMoney(float $n, string $symbol = '$', int $dp = 2): string
{
$sign = $n < 0 ? '-' : '';
return $sign . $symbol . number_format(abs($n), $dp, '.', ',');
}
echo formatMoney(1234.56), "\n";
echo formatMoney(-1234.5), "\n";
echo formatMoney(1234.5, '£'), "\n";
Discussion