magarrent/laravel-currency-formatter
composer require magarrent/laravel-currency-formatter
vendor/magarrent/laravel-currency-formatter/src are the fastest source of truth.php artisan vendor:publish
Then look for the package's config file (typically config/currency-formatter.php) and the currency map inside it.{{-- amount stored as 1299.5, currency code stored separately --}}
{{ Currency::format($product->price, $product->currency) }}
or, if the package exposes a helper:
{{ currency_format($product->price, 'USD') }}
USD, EUR, JPY). The formatter is a presentation concern; your schema should stay currency-aware.Keep formatting at the edges. Persist raw amounts and format in controllers/resources/views. Never store a formatted string as the source of truth.
Model accessor for display values. Avoid repeating the formatter call across views:
public function getFormattedPriceAttribute(): string
{
return Currency::format($this->price, $this->currency);
}
Keep the original price and currency attributes available for calculations.
API resources: return both raw and formatted.
return [
'amount' => $this->price,
'currency' => $this->currency,
'formatted' => Currency::format($this->price, $this->currency),
];
Clients that need to compute should use the raw value; formatted output is for display only.
Multi-currency lists. When a collection mixes currencies (orders, invoices, carts), format per row using each row's currency code rather than a single global default. Configure a default currency for the common case, but always pass the code explicitly where it varies.
Per-user currency preference. Store the user's preferred currency and format at render time. If you actually need conversion between currencies, do it in your own service layer before formatting — do not assume the formatter converts.
Emails, PDFs, and invoices. Format server-side before handing data to the view. This keeps Blade, mail, and PDF output consistent and avoids duplicating formatting logic in JavaScript.
Wrap it. Put a thin MoneyFormatter/PriceFormatter service around the package:
class PriceFormatter
{
public function format(float $amount, string $currency): string
{
return Currency::format($amount, $currency);
}
}
This gives you one place to swap implementations (e.g., to akaunting/laravel-money or native NumberFormatter) if the package stalls.
Testing. Assert exact strings, including separators and symbols:
$this->assertSame('$1,299.50', Currency::format(1299.5, 'USD'));
Pin the config in tests so locale or default-currency changes don't silently break assertions.
usd vs USD may behave differently; verify unknown-code behavior (exception vs silent fallback) in the source.$0.30 from 0.1 + 0.2 issues. Store minor units as integers or use decimal columns, and format at the last step.app()->getLocale(). If you support multiple locales, confirm whether the package uses NumberFormatter/intl or a fixed config, and test 1.234,56 vs 1,234.56 output.$ covers USD, CAD, AUD, and more. Show the currency code in checkout, invoices, and anywhere a wrong assumption is costly.\u{00A0} or compare normalized output.php artisan config:cache (and clear it locally with config:clear). Stale cached config is a common "why didn't my symbol change" cause.composer.json. Budget for replacing it with NumberFormatter or a more actively maintained money package if requirements grow.How can I help you explore Laravel packages today?