padam87/money-bundle
A Symfony bundle that integrates moneyphp/money, providing Doctrine mapping types, form types, and Twig helpers for storing, formatting, and working with monetary values and currencies safely in your application.
What changed, and why it matters. v0.6.0 is not an incremental release. The single PR in the changelog ("Refactored to use brick/money") replaces the bundle's entire underlying value-object library: moneyphp/money is gone, brick/money is in. Every public surface this bundle owns — the DBAL type mapping, the DI service signatures, the Twig filters, the form types — is downstream of that swap. This is a breaking change wearing a minor-version number, which is permitted under 0.x semver but not signalled in the release notes (no BREAKING marker, no migration guide, no upgrade section).
Framing correction still stands. This remains a Symfony bundle, not a Laravel package: a thin integration layer over a money library, with no service provider, facade, Eloquent cast, or Blade directive. What changed is which library it wraps. The prior assessment's split — durable library beneath, replaceable glue above — is unchanged; only the identity of the durable library is now in question.
Architecture fit. For Symfony + Doctrine + Twig, fit is still structurally sound, but the swap rewrites the semantics your application sees. moneyphp/money is an integer-minor-units library: Money::USD(1999), immutable, allocation-safe, no rounding concept because there are no fractional units. brick/money is a decimal-and-scale library built on brick/math: Money::of('19.99', 'USD'), a Context carrying scale and rounding mode, RationalMoney for division, ISO currency metadata, and cash-rounding support. These are different data models, not different APIs for the same model. Adopting v0.6.0 is choosing decimal-string-with-context over integer-minor-units. For Laravel, fit remains poor by construction, and now additionally means depending on a library whose model differs from the one the previous assessment recommended you implement.
Integration feasibility. Unchanged in shape, changed in substance:
composer update.moneyphp/money directly and write ~100 lines" — now needs a deliberate library choice rather than a default. brick/money is a defensible pick if you want context-based rounding, ISO currency data, and cash rounding out of the box; moneyphp/money remains simpler and integer-native. Pick one, record why, and forbid the other via a composer conflict entry so a transitive dependency cannot introduce two money models into one codebase.Technical risk. Elevated from the prior assessment, and the prior assessment's prediction has now materialized: it flagged "unpinned upstream release changing DBAL type behavior on a routine composer update" as a failure mode; v0.6.0 is that failure mode, at a larger blast radius than anticipated. Additional risk factors:
brick/money depends on brick/math and requires ext-bcmath or ext-gmp. Verify both against your base images, CI runners, and any shared hosting or serverless targets. This is an environment change, not just a Composer change.Key questions to resolve before any commitment.
brick/money, brick/math, and doctrine/dbal majors are supported by the tagged constraint set, and which Symfony majors?Context does the bundle register by default — scale and rounding mode — and can it be overridden per service, per currency, or per operation? Defaults here silently become your accounting policy.null amounts, negative amounts, and zero-decimal (JPY) and three-decimal (BHD, KWD) currencies handled by the type and the Twig filter?RationalMoney exposed for allocation and proration, or does the bundle force premature rounding at intermediate steps? (Intermediate rounding is the classic source of split-payment drift.)Stack fit. The layering advice is unchanged and now more important: treat the library as the dependency and the bundle as optional glue. Which library is a decision you should make explicitly, not inherit from a bundle's release cadence.
Decision rule.
brick/money's model.Migration path (0.5.x → 0.6.0, Symfony).
0.5.1, not ^0.5) so a routine update cannot land the swap.ext-bcmath/ext-gmp availability across every environment before writing code.Context, and round-trip a representative slice of real amounts through the DBAL type.Migration path (greenfield / Laravel).
composer conflict against the other.float for currency.DECIMAL/float with an explicit rounding mode; keep the legacy column readable during a dual-read window.Compatibility. Pin to an exact version or commit for anything 0.x, and write the reason in composer.json. Do not express this dependency as ^0.6 — the next refactor will arrive the same way this one did. If you later add a Symfony service alongside a non-Symfony stack, re-evaluate the bundle then; do not adopt it now for anticipated future fit.
Sequencing. Environment prerequisites → library/library-boundary decision → storage format → backfill/reconcile → presentation → business rules (rounding policy, allocation) → observability. Rounding policy must land in its own change with its own review; it is the thing that produces incidents.
Maintenance. Assume you own the code regardless of adoption. If you adopt, vendor or fork into your monorepo and pin the commit; do not rely on upstream responsiveness, and do not rely on the release notes to tell you a breaking change happened — 0.6.0 did not. Budget re-verification work on every brick/math, brick/money, Doctrine DBAL, and Symfony major, plus the PHP extension baseline.
Support. Unchanged: no vendor, no SLA, no community of scale. A 4-star, 0-dependent repo means the issue tracker is one person's inbox, and there is no downstream population to surface bugs before you do. The real support artifact is internal documentation of the currency storage format, the Context defaults, and the rounding policy — that document is now out of date and must be rewritten.
Scaling. Runtime cost stays negligible; both libraries are CPU-bound arithmetic. Two scaling risks are now live:
moneyphp/money and some on brick/money, converting at boundaries. Conversions between the two are lossless only if nobody rounds in between — and someone always rounds in between.Failure modes to watch.
composer update on a ^0.5 constraint silently landing v0.6.0 in a staging build. This is the top risk and it has already happened once in the wild.Context scale and rounding mode inherited without review, silently setting accounting policy.ext-bcmath/ext-gmp on one environment class — passes locally, fails at deploy.Ramp-up. A mid-level engineer is productive with either library in a day; both APIs are small and documented. The bundle remains a thin, non-obvious layer costing a second mental model. Reserve the real ramp-up for the money domain — rounding policy, allocation, tax — and add a short internal note on which library the codebase uses and why, since "the money library" is no longer a stable phrase in this codebase.
TPM recommendation (revised). The recommendation to not make this bundle a strategic dependency is unchanged and is now better supported: v0.6.0 demonstrates that a 0.x, single-maintainer bundle will rewrite its foundational abstraction without a migration guide, and your integration cost is set by that decision, not by yours. Choose the underlying library deliberately — brick/money if you want context-based rounding, ISO currency data, and cash rounding; moneyphp/money if you want integer-native simplicity — own the ~100–150 lines of integration your stack actually needs, pin exactly, and forbid the unchosen library at the Composer level. Revisit the bundle only if the organization standardizes on Symfony with Doctrine. The opportunity score of 15.94 and 0 dependents still point the same direction: this is low-leverage glue, and the value lives in the library beneath it — a library you should now pick on purpose rather than by inheritance.
How can I help you explore Laravel packages today?