NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Money for Laravel

Amounts & precision

A minor amount is always a canonical integer string: 0, or an optional minus followed by up to 65 significant digits (Money::MAX_DIGITS) — no plus sign, leading zeros, whitespace, dot or exponent. minor() only ever returns this grammar.

$big = Money::ofMinor('123456789012345678901234567890', 'EUR');

$big->digits();      // 30
$big->fitsInt();     // false
$big->minorInt();    // throws AmountOverflow — no silent (int) path

// Never compare raw minors in PHP: numeric strings go through float above int64
$a->minor() > $b->minor();   // unreliable for large amounts
$a->isGreaterThan($b);       // always exact

Money::ofMinor('007', 'EUR')->minor();   // "7" — normalized on entry
Money::ofMinor('5.0', 'EUR');            // throws InvalidAmount — minors are integers
  • Never (int)-cast or PHP-compare raw minors — PHP compares numeric strings through floats above int64. Use the Money comparison methods.
  • minorInt() is the only int bridge; it throws AmountOverflow outside int64, and fitsInt() tells you in advance.
  • JSON carries minor as a string: a JSON number above 2⁵³ is corrupted by JavaScript.
  • Integer inputs are normalized on entry ("007" → "7", "-0" → "0"); "+5", " 5", "5.0" and "5e3" throw InvalidAmount.

Limits

BoundValueException
Minor digits in memory65AmountOverflow
Decimal input digits90InvalidAmount
Parser input (characters)128InvalidAmount
split() parts1..10 000InvalidAllocation
Scales (MinorUnits, ofScaled, toScaled)0..36InvalidAmount
Custom currency exponent0..18InvalidCurrency
Ratio terms after reduction (digits)80InvalidRatio
Persisted digits (schema.precision)38InvalidMoneyValue

Database columns

$table->money() emits a signed decimal(P, 0) amount column (P = money.schema.precision, default 38) plus a currency column. Decimal gives native numeric ORDER BY, range filters and exact SUM — bigint would bring back the int64 ceiling, and varchar sorts “9” after “10”.

EngineColumnPDO returnsOut of range
PostgreSQLnumeric(38,0)string "1050"numeric_value_out_of_range error
MySQL / MariaDBdecimal(38,0)string "1050"Strict-mode out-of-range error (non-strict MySQL is unsupported)
SQLitenumericint 1050Would silently become REAL — so the cast refuses amounts beyond int64

The scale is always 0 — the exponent lives in the currency registry, so one column holds JPY (0), EUR (2) and ETH (18) rows. Lower money.schema.precision to 19 for int64-sized columns; Currency::maxMajorAmount() reports the largest storable major amount:

Currency::of('EUR')->maxMajorAmount(19);   // "99999999999999999.99"

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 crypto

By 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.