Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Money Laravel Package

brick/money

Brick\Money is a PHP library offering immutable Money and Currency classes with exact arithmetic and explicit rounding control, avoiding floating-point errors. Built on brick/math, it handles any amount size. Requires PHP 8.2+; GMP or BCMath recommended for speed.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

brick/money is a domain library, not a Laravel package: there is no service provider, config file, facade, migration, or Eloquent trait. That is not a defect — it is a deliberate scope choice — but it means it slots into the model layer, not the framework layer. For a TPM the relevant question is not "does it integrate with Laravel" but "where in our domain do we want a single, replaceable money abstraction."

The fit is strongest where money is currently handled as float, decimal, or bare integers with implicit currency:

  • Pricing, discounts, tax, and cart totals (especially where percentage math produces sub-cent results).
  • Invoicing, refunds, and partial captures — RationalMoney lets you defer rounding to a single, auditable point.
  • Marketplace/split payouts — allocate() with explicit allocation modes encodes a policy decision that is otherwise buried in ad-hoc code.
  • Multi-currency reporting and carts — MoneyBag and the FX conversion layer give you a currency-safe aggregate type.
  • Cash-handling workflows (POS, retail) — CashContext models CHF-style 5-cent increments that a generic decimal type cannot express.

Fit is weaker where you need: persisted monetary columns with database-level arithmetic (SQL SUM, reporting joins), or a team with no tolerance for pre-1.0 semver. In those cases the library is still the right in-process representation, but you must own the storage and aggregation contract yourself.

Integration feasibility

High. composer require brick/money on PHP 8.2+, one transitive dependency (brick/math), MIT license, no extensions required but GMP/BCMath strongly recommended for performance. Nothing in the package reaches into framework internals, so Laravel 10/11/12 compatibility is essentially a PHP-version question, not a framework-version question.

The real integration work is ours and is modest but non-zero: an Eloquent cast (Money ⇄ BIGINT minor units + CHAR(3) currency), a validation rule for currency codes and scale, an API resource/formatter for display, and a config-driven default currency + default rounding policy. That is roughly 1–2 days of engineering for a first vertical slice.

Technical risk

  • Pre-1.0 semver. Releases are 0.x.y; breaking changes always start a new 0.x cycle. Pinning 0.14.* is safe, but the team must treat minor bumps as major bumps during review. This is the largest process risk, not a technical one.
  • ISO 4217 drift. Currency data ships with the library. Pre-1.0, changes to alpha-code lookups (EUR, USD) are breaking; numeric codes, country lookups, and historical currencies may change in minor releases. Anything that persists a currency code across time needs a test that asserts the code resolves.
  • Governance risk, not library risk. The library forces you to name a RoundingMode at every lossy operation. If there is no written rounding policy per use case (tax, discount allocation, FX, refunds), developers will pick modes inconsistently and you will get reconciliation defects that are hard to attribute. This is the failure mode I would actually budget for.
  • Data quality flags. The dataset shows Dependents: 0 and a release date of 2026-09-29 — both are almost certainly scraping artifacts (this is a widely depended-on library, and that date is in the future). Verify current versioning and download counts on Packagist before quoting either number upward.
  • No Laravel-native safety net. No published first-party recipes for casts, serialization to JSON, or Blade formatting. Serialization round-trips (Money through queues, caches, API payloads) need an explicit decision: persist minor units + code, never the object's string form.

Key questions

  1. Which monetary use cases are in scope for phase one — display formatting only, or arithmetic and persistence?
  2. Do we need RationalMoney (deferred rounding) or is per-operation Money with explicit modes sufficient?
  3. What is our canonical storage format — BIGINT minor units, or DECIMAL(19,4) plus scale metadata?
  4. Who owns the rounding policy document, and which modes are approved per use case?
  5. Do any workflows require cash rounding or non-ISO/custom currencies (crypto, loyalty points, historical currencies)?
  6. Is our PHP floor already 8.2, or do we need to pin 0.10 for 8.1?
  7. Will FX conversion rates come from the library's provider abstraction or from our own pricing service?

Integration Approach

Stack fit

Framework-agnostic and PHP-version-gated, which is the cleanest kind of fit: no Laravel version treadmill, no conflict with existing providers. Recommended shape is a thin application-owned boundary — a MoneyFactory/CurrencyRegistry service, an Eloquent cast, an Http resource formatter, and a validation rule — with the library confined to those adapters plus domain services. Do not let Brick\Money\* types leak into controllers or Blade templates; keep them in models and services so the representation stays swappable.

Migration path

Brownfield migration should be incremental and observable, not a big-bang refactor:

  1. Introduce the cast and a money config (default currency, default rounding mode, approved modes).
  2. Add a parallel column (amount_minor BIGINT, currency CHAR(3)) alongside existing float/decimal columns on one high-value table.
  3. Dual-write with a backfill job, converting via Money::ofMinor() on read and asserting equality against the legacy column in a nightly check.
  4. Move read paths (calculations, API output) to the new columns behind a feature flag.
  5. Drop legacy columns only after a full billing/reconciliation cycle shows zero drift.

For greenfield, start with minor-unit integers from day one; do not introduce decimal columns "for readability."

Compatibility

Requires PHP 8.2+ for current releases (0.10 for 8.1, 0.8 for 8.0). The library tracks the latest ISO 4217 standard, so compatibility includes data compatibility, not just code compatibility. brick/math must be allowed to float within the range the chosen brick/money cycle supports — pin both or pin neither, but pin consistently. GMP or BCMath should be present in the production image; without them the library still works but falls back to slower pure-PHP arithmetic.

Sequencing

Phase 1: config, cast, validation rule, formatter, and the rounding policy doc. Phase 2: one vertical slice (cart totals or invoice lines) with dual-write and reconciliation. Phase 3: RationalMoney for any multi-step calculation (tax-then-discount-then-FX) where intermediate rounding currently causes drift. Phase 4: allocation/split for payouts and refunds, with the chosen AllocationMode documented as a business rule. Phase 5: MoneyBag and FX providers only once genuine multi-currency reporting is on the roadmap.

Operational Impact

Maintenance

Low code churn, moderate process churn. The library is stable and well tested, but the 0.x cadence means someone must own upgrade reviews, and currency-data updates arrive with releases rather than as separate data packages. Budget a recurring task: read the changelog on each 0.x.0, run the currency-code assertions, and confirm rounding behavior is unchanged. Because there are no framework hooks, there is nothing to keep in sync with Laravel releases — a genuine long-term win.

Support

Support burden shifts from "why is the library broken" to "why did this total change by a cent." Expect tickets about rounding, not about crashes. Mitigations: log the rounding mode used on any lossy operation, surface currency and minor units in admin views, and keep an audit trail of the pre-rounding rational value for high-value flows (invoices, payouts). The library's exception messages are specific and actionable, which shortens triage.

Scaling

Effectively free. Immutable value objects, pure in-process arithmetic, no I/O, no state, no caches. With GMP/BCMath the operations are fast enough that this will never appear in a profile. The one scaling consideration is at the data layer: aggregate reporting must sum integers or decimals in SQL, not hydrate thousands of Money objects — so the storage schema decision made during integration is what actually determines reporting performance.

Failure modes

  • RoundingNecessaryException at runtime wherever a mode was omitted — the most likely production incident, and it is a design signal rather than a bug. Enforce modes at the service boundary so this never reaches a user request.
  • CurrencyMismatchException on cross-currency arithmetic — desirable, but needs a user-facing translation in API error handling.
  • UnknownCurrencyException on ISO data changes or user-supplied codes — validate at input, and assert persisted codes resolve after every upgrade.
  • AutoContext with an infinite repeating decimal throws rather than approximates; document that it is unsuitable for intermediate results and steer developers to RationalMoney.
  • Serialization drift — queue payloads or cached models holding a stringified money value can silently change meaning if the context or scale differs on rehydration. Persist minor units and currency code; reconstruct explicitly.
  • Missing GMP/BCMath is a performance degradation, not an outage, but it should be caught in the Dockerfile so it doesn't surface as a mystery slowdown.

Ramp-up

A competent PHP developer is productive in half a day for basic of()/plus()/minus(). The genuine learning curve is conceptual: contexts (default vs. cash vs. custom vs. auto), the difference between Money and RationalMoney, and why rounding is never implicit. Plan a one-hour team session plus the written rounding policy — without that doc, the library's main safety feature (forced explicitness) becomes a source of inconsistent decisions rather than a control.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
thomas-0816/doctrine-dbal-duckdb
moyisoft/laravel-admin
oxygen/mod-pages
oxygen/mod-import-export
oxygen/mod-media
ksoft/laravel-contentbuilderjs
ourgoldpackages/exchange
mikkimike/laravel-exchange1c
wandesnet/mercadopago-laravel
tsfcorp/email
larafony/core
laravel-enso/currencies
tartan/laravel-online-payment
gam/laravel-sat-catalogs
cloudcreativity/laravel-stripe
abdulelahragih/querybuilder
wedevbr/celcoin-laravel
surazdott/nepali-date
devsquad-cockpit/laravel
coding-socks/laravel-upload-handler