finller/laravel-money
Laravel Money offers a convenient Money value object for Laravel apps, with Eloquent casts, currency-aware arithmetic, and formatting helpers so you can store, calculate, and display monetary values safely without floating-point errors.
composer require finller/laravel-money. The package wraps brick/money, so ext-bcmath is required in local, CI, and production environments.php artisan vendor:publish --tag="laravel-money-config". Set default_currency and default_context explicitly; do not rely on implicit defaults across environments.Money class, the Eloquent casts, the validation rules, and config/laravel-money.php. Because the package is thin, also keep the Brick/Money docs open for rounding, contexts, and formatting behavior.// config/laravel-money.php
return [
'default_currency' => 'USD',
'default_context' => Brick\Money\Context\DefaultContext::class,
];
use Finller\Money\Casts\AsMoney;
class Order extends Model
{
protected $casts = [
'total' => AsMoney::class,
];
}
use Finller\Money\Money;
$order = Order::create([
'total' => Money::of('19.99', 'USD'),
]);
$order->total->formatTo('en_US'); // "$19.99"
That covers the first day-to-day use case: store a monetary value, retrieve it as a value object, and render it without floats.
Money objects inside the domain. Do not pass request strings through several layers.use Finller\Money\Money;
$money = Money::parse($request->input('total'), 'USD');
use Finller\Money\Rules\MoneyRule;
$validated = $request->validate([
'total' => ['required', new MoneyRule()],
]);
$order->total = Money::of($validated['total'], 'USD');
AsMoney keeps model attributes as value objects and handles serialization. If the app supports multiple currencies per record, use the package’s money-bag cast where available, or store a currency column and construct Money explicitly.plus(), minus(), multipliedBy(), and allocate() are immutable and context-aware. Use isEqualTo(), isGreaterThan(), etc. instead of loose comparisons.DefaultContext allows fractional minor units; CashContext rounds to cash increments. Pick one per currency and keep it consistent between writes and reads.formatTo($locale) in Blade/API resources, or use Brick’s IntlMoneyFormatter when you need full control. Return a string and, if needed, a minor-unit integer in APIs—never a float.phpunit.xml or TestCase setup so behavior does not depend on a developer’s local .env.ext-bcmath is non-negotiable. Missing bcmath is the most common install-time failure. Add it to Docker images and CI setup.Money::of(0.1 + 0.2, 'USD') produces the wrong amount. Use strings like '0.30' or integer minor units.DefaultContext and reading with CashContext can round or throw. Configure one default and use it everywhere.default_currency silently reinterprets historical data. Store currency explicitly for anything multi-currency.AsMoney writes to the column—typically a string such as "USD 19.99". Treat that format as part of your database contract; changing cast versions or serialization requires a backfill."1,234.56", "1.234,56", "$10", and negative values. Locale-dependent parsing is ambiguous; prefer ISO currency codes and machine-readable amounts.formatTo('en_US') and formatTo('de_DE') produce different separators. Do not format once and parse the formatted string back.$money->plus($tax) returns a new object; it does not mutate $money. Reassign the result.dd($model->total) shows the Money object; inspect (string) $model->total, getAmount(), getCurrency(), and getContext() when persistence looks wrong.How can I help you explore Laravel packages today?