Product Decisions This Supports
- Pricing, billing, and invoicing feature work. Any roadmap item that touches money — subscription pricing, invoices, refunds, payouts, discounts, multi-currency catalogs — carries a recurring defect class: floating-point rounding drift and accidental mixing of currency units. A cast that maps an integer column to a Money object at the model boundary turns that from a per-feature engineering discipline into a framework-level default. This is a leverage decision, not a feature.
- Data model and storage convention. The package encodes a decision: money is stored as integer minor units and only becomes a decimal at the presentation edge. If the product currently stores
DECIMAL or FLOAT for prices, this is the moment to decide the convention, because it is far cheaper to standardize before a second team or a reporting pipeline depends on the existing schema.
- Build vs. buy. The capability is a few hundred lines: a cast, a currency code source, formatting helpers. Buying is the correct default — writing it in-house means owning rounding, negative amounts, locale formatting, and serialization forever. But at 5 GitHub stars and a single maintainer, the honest framing is buy, with a fork contingency: budget the cost of vendoring it internally as a small, contained file if the maintainer disappears, and confirm MIT licensing makes that a copy-paste, not a negotiation.
- Phased adoption / migration sequencing. Because it is an opt-in cast per model attribute, adoption is incremental — one model at a time, behind tests. That lets you decouple "standardize money handling" from "migrate the schema," which is the difference between a two-day task and a quarter-long initiative.
- Reporting and analytics accuracy. Integer storage means SQL
SUM is exact and reproducible, and currency formatting moves entirely to the presentation layer. This affects how the data team writes aggregates and how API contracts expose amounts — decide early whether the API emits minor units (integers) or formatted strings, because changing that later is a breaking contract change.
- Multi-currency roadmap confidence — with a caveat. "Configurable currency codes" suggests currency is configured, not necessarily stored per row. If the product roadmap includes per-record or per-transaction currency (a customer billed in EUR, a vendor paid in GBP), validate that the cast reads currency from the record rather than a global config before committing to it. This is the single most likely mismatch between the package's design and a real multi-currency domain.
- Dependency hygiene (secondary signal). The v1.11.0 Laravel 13 compatibility release means this dependency is not on the critical path for a framework upgrade, and the maintainer is tracking upstream. That is a maintenance-health signal, not a product capability — it should inform the risk register, not the roadmap.
What this package does not decide for you: FX conversion, tax computation, rounding strategy per jurisdiction, ledger/double-entry semantics, or price-change auditing. If those are on the roadmap, this package is an ingredient, not a solution, and the buy-vs-build calculus shifts substantially.
When to Consider This Package
Adopt when:
- You are building on Laravel (11/12/13) with Eloquent models that hold monetary attributes, and you want a small, MIT-licensed, single-purpose dependency rather than a custom cast.
- Your money model is simple: a fixed set of currencies, amounts stored as integers, formatting and basic arithmetic needed, no FX.
- You want the schema change to be gradual and reversible — an opt-in per-attribute cast fits that.
- You are a small team without a payments specialist, where adopting a convention is cheaper than documenting one.
Look elsewhere, or write the cast yourself, when:
- You need per-record currency. Verify first; if currency must vary by row, a config-driven cast is the wrong shape and you will end up wrapping it anyway.
- You need a mature money library.
moneyphp/money (or brick/money) is the ecosystem standard and has years of edge-case hardening. Pairing it with a thin Laravel cast is a legitimate, arguably lower-risk alternative — you get a well-tested arithmetic core and own only the integration glue.
- You need FX, tax, rounding policies, or locale-aware formatting. Out of scope; do not assume adjacent capability.
- Bus factor matters to your org. 5 stars and a single maintainer is the real risk here, not code quality. If your dependency policy requires a track record (issue responsiveness, multiple contributors, adoption breadth), this fails that bar — and you should say so explicitly rather than discovering it during an incident.
- You need guarantees about the integer/float boundary. The one-line description mentions converting stored integers to floats, while the feature description promises Money objects. That discrepancy is worth 15 minutes of reading the source: confirm no float ever touches arithmetic, confirm rounding mode, confirm behavior for negative amounts (refunds, credits), and confirm what is emitted when a model is serialized to JSON — a formatted string appearing where an API consumer expects an integer is a breaking change waiting to happen.
- You need DB-level enforcement. A cast protects application reads/writes; it does not stop a raw SQL update or a
where('price', '>', 9.99) comparison in query builder from going wrong. Queries must still use minor units — that convention needs a written standard or it will erode.
Cheap verification before committing (do these, they are all under an hour):
- Read the cast source — check for float usage, rounding behavior, negative handling, and JSON serialization.
- Confirm Laravel and PHP version constraints against your actual runtime image.
- Confirm test coverage exists and CI runs against your current framework version.
- Confirm the minimum supported framework version was not raised in a way that freezes you on an old patch line.
- Prototype on one model with one real invoice scenario, including a refund.
How to Pitch It (Stakeholders)
To executives (one paragraph): We have a small, free, open-source component that standardizes how our application handles money. The problem it addresses is real and expensive when it goes wrong: prices stored as decimals accumulate rounding errors, and currencies get mixed by accident, which shows up as billing discrepancies and reconciliation work. Adopting it is a low-cost convention decision — a few days of engineering, no license fee, and it can be rolled out one model at a time and reversed. The main risk is not cost, it is concentration: it is maintained by one person with a small user base, so we would adopt it with a documented fallback of owning the code ourselves if it is ever abandoned. Recommendation: adopt for the pricing work already on the roadmap, on normal engineering cadence, and do not create a project around it.
To engineering (short): A Laravel cast that maps integer minor-unit columns to Money objects on Eloquent models, with configurable currency codes and display formatting. It is per-attribute and opt-in, so we can phase it model by model. Three things to settle before we write it into a standard: (1) verify the source does no float arithmetic and check rounding and negative-amount behavior; (2) decide and document the API contract — we expose minor units as integers, not formatted strings, or we accept that as a breaking change later; (3) queries still need integer values, so the cast does not protect query builder or raw SQL — treat "amounts are integers in the database" as a written convention, not an assumption. Keep moneyphp/money on the table as the arithmetic core if we hit anything beyond simple arithmetic. The v1.11.0 Laravel 13 compatibility bump is maintenance hygiene — it clears a dependency from the upgrade blocker list, and it should not be conflated with a reason to adopt or upgrade anything.
Framing to avoid: don't sell this as "our money problems are solved." It solves representation and formatting at the model boundary. It does not solve FX, tax, rounding policy, reconciliation, or ledger integrity — and if someone hears otherwise in the kickoff, you will spend the next quarter correcting that expectation.