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

Dough Laravel Package

merk/dough

Dough is a lightweight money value object for Laravel and PHP, with currency-aware arithmetic, parsing, formatting, comparisons, and Eloquent casts. Handle prices, totals, taxes, and conversions safely using immutable amounts and avoid floating-point errors. Includes helpers for common money operati...

Deep Wiki
Context7

Technical Evaluation

What it is. merk/dough is a standalone immutable Money value object, a direct port of Kent Beck's TDD-by-Example implementation. It is not a Laravel package — there is no service provider, config file, facade, or Eloquent integration. It is a small, framework-agnostic domain primitive that Laravel can consume the same way any Composer library is consumed.

Architecture fit. Reasonable fit for a domain-layer value object in a DDD/hexagonal Laravel application: put it in app/Domain/Support or a dedicated internal package and keep it out of controllers and Blade templates. It is a poor fit for teams following Laravel's default idiom of decimal columns plus number_format() helpers, because adopting Dough forces a discipline change (integer minor units + explicit currency) across every layer. It also overlaps almost entirely with moneyphp/money (the de facto PHP standard) and brick/money, both of which have materially larger feature surfaces (allocation, rounding modes, currency repositories, parsers, formatters).

Integration feasibility. Mechanically trivial — composer require plus PSR-4 autoloading. The real friction is version constraint compatibility. A release dated 2016-01-18 predates PHP 7.1, and its composer.json will almost certainly pin php: >=5.x and dev-dependencies (PHPUnit 4/5-era) that conflict with Laravel 9/10/11's PHP 8.1+ requirement. Expect Composer resolution failures; --ignore-platform-reqs in CI is not an acceptable workaround. The practical path is a fork into an internal namespace with an updated constraint block.

Technical risk. High, and asymmetric — the upside is modest, the downside is a long-lived liability.

  • Abandonment: no release in eight-plus years, 21 stars, effectively a single maintainer, and the repository is unlisted/unverifiable ("unknown"), so upstream activity cannot be assessed. Score 0.325 is consistent with this.
  • Correctness: Kent Beck's implementation is pedagogically clean but was never hardened for FX conversion, proportional allocation, banker's rounding, or jurisdiction-specific tax rounding. Whether those gaps matter depends entirely on the product's money semantics.
  • Security: negligible attack surface — pure computation, no I/O, no deserialization of untrusted payloads. This is the one genuine point in its favor.
  • API opacity: currency representation (string vs. object), rounding policy, overflow behavior on large amounts, and JSON serialization contract are all unverified.

Key questions to resolve before committing.

  1. Does Composer resolve cleanly against our PHP 8.x / Laravel version, or is a fork mandatory?
  2. Does its test suite exist, run green on PHP 8.x, and what is the coverage of arithmetic and comparison operators?
  3. How is currency modeled, and does it fail loudly or silently on mismatched-currency arithmetic?
  4. What rounding mode(s) are supported, and do they satisfy finance/accounting requirements?
  5. Are amounts backed by native integers (overflow risk on 32-bit, and on large values generally) or arbitrary-precision?
  6. Is it safely serializable across queue boundaries (jobs, events, Octane worker reuse)?
  7. What is our exit cost to brick/money or moneyphp/money if we adopt it today?

Integration Approach

Stack fit. Technically zero-friction, idiomatically awkward. Because it is pure PHP, it drops into any layer — form requests, jobs, domain services, policies — but nothing in Laravel knows about it. Every boundary (database, JSON API, queue payloads, Blade formatting) requires an explicit adapter written by us.

Compatibility. Treat compatibility as unproven until a spike proves it. Requirements: Composer install on our exact PHP version, the upstream test suite executed under PHP 8.x, a round-trip serialization test (serialize/unserialize and an Eloquent-to-queue-to-worker cycle), and an overflow test at both 32-bit and realistic 64-bit ceilings. If any of these fail, vendor the source into an internal package rather than patching in vendor/.

Migration path. Adopt behind an anti-corruption layer, not directly.

  • Define an internal contract — App\Support\Contracts\Money — exposing only the operations we actually need (add, subtract, multiply, equals, isGreaterThan, getAmount, getCurrency).
  • Implement DoughMoney as the first adapter. Application code type-hints the interface only.
  • Add an Eloquent custom cast persisting amount_minor (BIGINT) and currency_code (CHAR(3)) as separate columns. Never store floats.
  • Swapping to brick/money later becomes a one-class change plus a container binding, with no call-site churn.

Sequencing.

  1. Spike (1–2 days): fork, fix constraints, run tests, write compatibility findings.
  2. Decision gate: if the spike surfaces rounding, currency, or precision gaps that touch revenue logic, stop and go straight to brick/money — the effort saved is not worth the ownership burden.
  3. Contract definition: agree the internal Money interface with domain and finance stakeholders.
  4. Persistence layer: migrations to integer minor-unit columns, cast implementation, backfill of any existing float data with reconciliation reports.
  5. Incremental adoption: migrate one bounded context (e.g. cart totals) first, dual-run against the legacy calculation, and diff results before cutting over.
  6. Formatting last: presentation-layer formatting stays independent of the Money object so locale/currency display can evolve separately.

Operational Impact

Maintenance. This becomes our codebase on day one. Budget for an internal owner, a vendored fork in a private repository, and a standing commitment to re-audit on every PHP major upgrade. Realistically a few days a year of maintenance — small in absolute terms, but it competes for attention against libraries with active upstreams.

Support. MIT with no SLA, no security advisory feed, no issue triage. There is no external escalation path; the internal owner is the support tier. Document that explicitly so it does not surface as an incident-time surprise.

Scaling. Computational cost is negligible — immutable value objects are cheap and allocation-bounded, and this will never be a throughput bottleneck. Two real scaling considerations: object churn in tight loops (batch operations should sum in integers, not construct thousands of Money instances), and serialization size for queue payloads and API responses, where a lean array representation is preferable to serializing the object graph.

Failure modes to design against.

  • Silent currency mismatch — arithmetic across currencies that throws only sometimes, or worse, does not throw at all.
  • Rounding drift — accumulation errors from line-item rounding, surfacing at invoice or reconciliation time rather than at write time.
  • Serialization breakage — queue payloads becoming unreadable after a package or PHP upgrade; version the serialized shape.
  • Composer lock contention — an abandoned dependency blocking an unrelated, security-driven framework upgrade months later. This is the most likely and most expensive failure.
  • Overflow — large-amount edge cases in reporting or aggregation, tested only in production.

Ramp-up. The API is small and the Money pattern is well-understood, so individual ramp-up is a few hours. The organizational ramp-up is the real cost: developers accustomed to float arithmetic will need a written convention (integers in, integers out, explicit currency everywhere), review checklist items, and at least one worked example in the codebase. Onboarding friction is higher than with moneyphp/money, where prior exposure is far more common and documentation is external and maintained.

Recommendation. Do not adopt for greenfield. The package is technically sound and architecturally inoffensive, but it is abandoned, unverifiable, and functionally a subset of a well-maintained alternative; the only durable benefit is negligible security surface. If existing code already depends on it, contain it behind the adapter described above and schedule replacement. If the goal is simply "an immutable Money type in Laravel," brick/money delivers the same value with an active maintainer and a credible upgrade path.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin