The Money object
Money is a final readonly value object: an amount of minor units plus a Currency. Every operation returns a new instance. There is deliberately no Money::of() — the unit is always in the factory name.
Creating money
use RoundlyConsulting\Money\Money;
$price = Money::ofMajor('19.99', 'EUR'); // minor "1999" — never a float
$fee = Money::ofMinor(250, 'EUR'); // 2.50 EUR
$none = Money::zero('USD'); // 0.00 USD
Money::ofMajor('10.005', 'EUR'); // throws RoundingNecessary
Money::ofMajor('10.005', 'EUR', RoundingMode::HalfEven); // 10.00 EUR
Money::ofScaled(9990, 3, 'EUR'); // Apple milli-units → 9.99 EUR
Money::ofScaled(9990000, 6, 'USD'); // Google micros → 9.99 USD
Money::fromArray(['minor' => '1050', 'currency' => 'EUR']); // 10.50 EUR
Money::parse('1 234,50 EUR', locale: 'sk'); // 1234.50 EUR- ofMinor($minor, $currency) — an int or integer string of minor units; floats are a TypeError.
- ofMajor($amount, $currency, ?$rounding) — a whole int or a plain decimal string; over-precise input throws RoundingNecessary unless you pass a rounding mode.
- ofScaled($value, $scale, $currency, ?$rounding) — an integer at another scale (0..36): Apple milli-units are scale 3, Google micros scale 6.
- zero($currency) — a zero amount.
- parse($input, ?$currency, ?$locale) — localized input through the bound parser (see Formatting & parsing).
- fromArray($data) — the toArray() shape; when both minor and decimal are present they must agree.
A string currency resolves through the registry (trimmed and upper-cased), so 'eur' works; an unknown code throws UnknownCurrency.
Reading the amount
$total = Money::ofMajor('67.47', 'EUR');
$total->minor(); // "6747" — a string
$total->minorInt(); // 6747 — throws AmountOverflow beyond int64
$total->fitsInt(); // true
$total->digits(); // 4
$total->currency()->code; // "EUR"
$total->toDecimal(); // "67.47" — locale-free
$total->toScaled(3); // "67470"
(string) $total; // "67.47 EUR"
json_encode($total); // {"minor":"6747","decimal":"67.47","currency":"EUR"}toDecimal(trimTrailingZeros: true) drops trailing fraction zeros (and a bare dot). toScaled($scale) returns the amount as an integer string at another scale, rounding once when scaling down.
Serialization
toArray() and JSON carry minor as a string on purpose — JavaScript corrupts JSON numbers above 2⁵³. __toString() is deterministic and locale-free, ideal for logs and exception messages. PHP serialize() works too, so Money travels through queues with its full currency definition.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.