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

Getting Started

  • Install with composer require merk/dough. The last tagged release is from 2016, so expect Composer to complain on modern PHP — either add the constraint with --ignore-platform-reqs, loosen the php requirement in your root composer.json, or fork and patch. Verify the package actually resolves on PHP 8.x before building on it.
  • Read the source, not the README. This package grew out of Kent Beck's TDD-by-Example Money kata, so the test suite (if present) is the real specification. Start in src/ and look for the core types: a Money value object, a Bank (or Broker) that performs currency reduction, and an Expression/Sum abstraction for money arithmetic.
  • Confirm the exact API surface before designing around it — the canonical entry point is a factory on Money (e.g. Money::dollar(...)), multiplication via times(n), addition via plus(...), and comparison via an equality method. Signatures and whether amounts are integers or floats vary between kata-derived implementations, so grep for function in the Money class first.
  • First use case: model a unit price and quantity. $total = Money::usd(1999)->times($qty) — then persist $total by storing its integer amount and currency code, not by serializing the object.

Implementation Patterns

  • Treat it as a value object, always. Every operation returns a new instance. $price->times(3) on its own line silently does nothing; you must reassign: $price = $price->times(3). Enforce this in code review — it is the single most common bug with this pattern.
  • Wrap it in a domain type. Don't sprinkle Money across controllers and Eloquent models. Create App\ValueObjects\Price or a MoneyFactory that knows the app's base currency, then expose narrow methods (addTax, multiplyBy, format). This insulates you from the package being abandoned.
  • Persistence via a custom Eloquent cast. Store amount as BIGINT (integer minor units) and currency as CHAR(3). Write a cast that hydrates Money from the two columns and serializes back to them. Never store a float or a serialized object.
  • Currency conversion through a Bank. Instantiate a Bank, register rates once (ideally in a service provider or a small ExchangeRateService that reads from config/DB), and pass it into your domain service. Do not let the Bank become a global singleton that drifts from your real rate source — feed it fresh rates per request/job.
  • Validation layer. Add a FormRequest rule that rejects floats for monetary input and normalizes to integer minor units. Pair with brick/math or bcmath if you receive decimal strings and need exact parsing before constructing the Money object.
  • Composition over inheritance. Where you need addTax or withDiscount, compose a Money inside your own class rather than subclassing Money — subclassing couples you to the 2016 API and complicates equality.
  • Testing. Assert with the package's own equality method ($this->assertTrue($a->equals($b))), not assertEquals on the objects, unless the class implements full value equality. Build a small assertMoney helper in your test base class.

Gotchas and Tips

  • Abandoned since 2016. Assume no PHP 8 compatibility, no typed properties, no declare(strict_types=1), and possibly deprecated constructs. Budget for a fork. If the integration is non-trivial, seriously evaluate moneyphp/money — it is actively maintained, has a Laravel-friendly formatter, and covers the same pattern.
  • Float contamination. Kata implementations sometimes accept float or cast amounts. If you pass 19.99 instead of 1999, equality and rounding will bite you. Always construct with integer minor units and assert this in tests.
  • Equality, not identity. == compares all properties including possibly internal representation; === compares instances. Always use the intended equality method, and be aware that two Money objects with the same amount but different currency are not equal.
  • No formatting or localization. This package does arithmetic, not presentation. Handle display with NumberFormatter (intl) or a small presenter, and be explicit about decimal places per currency (JPY has zero, most have two, some have three).
  • No Laravel integration whatsoever. There is no service provider, facade, or config file. You must bind factories and the Bank in your own AppServiceProvider. Register a singleton only if the rates are static; otherwise resolve per request.
  • Bank state is mutable in practice. Rates you register live on the Bank instance. Don't share one instance across queued jobs or long-running Octane workers where rates may go stale — rebuild it or reset it.
  • Serialization for queues. PHP's default serialize() of the object may work, but the class shape is frozen at 2016. Prefer passing scalar DTOs (amount + currency) across job boundaries and rehydrating.
  • Extension points are minimal. The main hooks are implementing the Expression interface and providing your own Bank/rate strategy. Anything richer (rounding policies, allocation/splitting) likely isn't there — check for allocate/split before promising it, and implement your own if missing.
  • Pin the version and record the decision. Add a note in your ADR or README explaining why this package was chosen and what the exit path is, since the maintenance risk is real at 21 stars and a 2016 release.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle