Library / SDK
moneyphp/money avatar
moneyphp/money

moneyphp/money: integer-safe money values for PHP applications

PHP implementation of Fowler's Money pattern.

4,870 stars445 forksPHPMIT

At a glance

What is it?
A PHP value object library that stores monetary amounts as strings instead of floats, with allocation, formatting and currency exchange built on top. Useful for any PHP codebase that touches prices, invoices or payouts.
Who is it for?
Adopt moneyphp/money if your PHP application stores or calculates monetary amounts and you want integer-safe arithmetic with explicit currency, and if you can run PHP 8.0 or newer with the BCMath extension available. Do not adopt it if you are on PHP 7.x and cannot upgrade, since version 4 requires PHP 8.0 and older releases are the only path there.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 85 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The float problem moneyphp/money exists to remove

The README opens with a quote from Bill Karwin: "If I had a dime for every time I've seen someone use FLOAT to store currency, I'd have $999.997634". That number is the argument. Binary floating point cannot represent most decimal fractions exactly, so repeated addition and multiplication of prices drift. The library's answer is a value object that holds an amount and a currency together, and since version 3.0 it stores the amount as a string internally, which the README describes as supporting unlimited integers. This is aimed at PHP developers writing e-commerce checkouts, invoicing, subscription billing, payroll, or any code that splits a total across parties. It is not a payment gateway, an accounting ledger, or a database layer. It is the arithmetic primitive you put underneath those things so that the numbers stop moving when you do not want them to.

What Money::EUR(500) actually holds, and why allocate matters

A Money instance is an amount plus a Currency. The README example constructs Money::EUR(500), which is five euros in minor units, and adds it to itself to get ten euros. The more interesting call is allocate. Given ten euros and a ratio of [1, 1, 1], allocate returns three parts of 334, 333 and 333 minor units. The remainder cannot be divided evenly, so it is distributed rather than lost, and the sum of the parts equals the original. That is the mechanism that matters for splitting a bill, distributing a discount, or apportioning a fee across line items. Doing the same thing with floats or with naive integer division leaves you either short a cent or over by one, and the discrepancy usually surfaces in a reconciliation report weeks later. The README also lists JSON serialization, a currency repository with ISO currencies included, money formatting including an intl formatter, and money exchange with a Swap implementation. The calculation backend is chosen transparently depending on what is available: bcmath, gmp, or plain PHP.

Installing moneyphp/money and running a first allocation

Installation is a single Composer command. The README gives it exactly as shown below. Composer resolves the package and its dependencies, and you should see the package added to your composer.json require block.

bash
$ composer require moneyphp/money

Once installed, the class you reach for is Money\Money. The README's own example builds two values, adds them, then splits the result three ways and asserts each part. Run this and the assertions pass; if you change the ratio, the returned parts change but still sum to the original amount.

php
<?php

use Money\Money;

$fiveEur = Money::EUR(500);
$tenEur = $fiveEur->add($fiveEur);

list($part1, $part2, $part3) = $tenEur->allocate([1, 1, 1]);
assert($part1->equals(Money::EUR(334)));
assert($part2->equals(Money::EUR(333)));
assert($part3->equals(Money::EUR(333)));

If you want to run the library's own test suite inside a container, the README describes building the image locally with docker build -t moneyphp . and then running phpunit inside it with the exclude-group segmentation flag.

Requirements that decide whether you can use it at all

The README states that the library requires the BCMath PHP extension, and that there may be additional dependencies for specific features, naming the Swap exchange implementation as an example. Version 4 requires PHP 8.0; for older PHP versions the README points to version 3. From version 4.5, the package only supports PHP versions that still receive updates from PHP itself, and the README notes that older versions of the package remain available for older PHP. This is the first thing to check in a legacy codebase. If you are pinned to PHP 7.x for reasons outside your control, you are on version 3, which the README describes as using strings internally from 3.0 onward, so the core representation is the same even though the release line differs. The BCMath requirement is less negotiable: the README lists it as a requirement, not an optional accelerator, even though the feature list mentions gmp and plain PHP as alternative calculation paths.

Where moneyphp/money is the wrong tool

This library does arithmetic. It does not decide your rounding policy, and it does not store anything. If your problem is that two services disagree about the total of an order, adding Money to one of them will not fix the disagreement; you need a single place where the amount is computed and a schema that stores minor units with a currency code. The exchange feature is the other place to be careful. The README names Swap as an implementation and points to the documentation for additional dependencies, which means exchange rates are a component you supply or configure, not something the library fetches for you. If you were hoping for live rates out of the box, the README does not promise that. Finally, if your amounts are always whole numbers of a single currency and never split, a plain integer column may be simpler than a value object, and the library's value shows up precisely when currency and allocation enter the picture.

How it compares to brick/money and plain integers

The closest alternative in the PHP ecosystem is brick/money, which also models an amount plus a currency and also avoids floats, but its design choices differ: it is built around a Money and Currency pair with its own contextual rounding and a separate MoneyBag for mixed-currency containers, and it targets modern PHP versions with a different extension story. If your team already depends on brick packages, staying inside that ecosystem keeps your dependency graph smaller. The other alternative is not a library at all: store amounts as integers in minor units and write the arithmetic yourself. That works until you need to split a total across parties, format for a locale, or convert between currencies, at which point you are reimplementing allocate and the ISO currency table. moneyphp/money is the older, more widely installed option of the two libraries, and its README is explicit that it was inspired by Martin Fowler's Money pattern, which is the vocabulary most PHP developers will already recognize.

Maintenance, licence and the cost of upgrading

The repository is not archived, and the last push was on 2026-07-07. Recent releases are v4.9.0 on 2026-05-04, v4.8.0 on 2025-10-23 and v4.7.1 on 2025-06-06, so the release cadence is roughly a minor version every few months rather than continuous churn. The licence is MIT, which permits commercial and closed-source use with the usual requirement to keep the copyright and permission notice; this is a description of the licence text, not legal advice, and your own counsel should confirm how it interacts with your distribution model. The upgrade cost is concentrated in the PHP version floor. The README states that from version 4.5 the package only supports PHP versions that PHP itself still updates, which means a future PHP end-of-life can force a package upgrade on you. The Dockerfile in the repository pins php:8.0-cli and installs intl, bcmath and gmp plus a set of locales, which is a reasonable template for the extensions and locale data your test environment needs if you format money with the intl formatter.

Editorial conclusion

Adopt moneyphp/money if your PHP application stores or calculates monetary amounts and you want integer-safe arithmetic with explicit currency, and if you can run PHP 8.0 or newer with the BCMath extension available. Do not adopt it if you are on PHP 7.x and cannot upgrade, since version 4 requires PHP 8.0 and older releases are the only path there. Before committing, verify that BCMath is enabled in your runtime, and check the doc directory for the exchange implementation you intend to use, because the README states that some features carry additional dependencies such as the Swap exchange. The library does arithmetic and allocation; it does not persist anything, so your database schema and rounding policy remain your responsibility.

Frequently asked questions

What PHP version does moneyphp/money require?

The README states that version 4 requires PHP 8.0, and that for older versions of PHP you should use version 3 of the library. It also notes that from version 4.5 the package only supports PHP versions that still receive updates from PHP itself.

Does moneyphp/money need the BCMath extension?

Yes. The README lists the BCMath PHP extension under Requirements, and adds that there may be additional dependencies for specific features, giving the Swap exchange implementation as an example.

How do I install moneyphp/money?

Via Composer, with the command composer require moneyphp/money, which the README gives in its Install section. The official documentation is linked at moneyphp.org.

How does moneyphp/money split an amount without losing a cent?

The allocate method takes a list of ratios and returns that many Money values whose sum equals the original. In the README example, ten euros allocated as [1, 1, 1] returns 334, 333 and 333 minor units.

Official sources

  1. License: MIT
  2. moneyphp/money on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/moneyphp-money.svg)](https://hysenlabs.com/projects/moneyphp-money)