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 Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle and the underlying money library (it is pulled in transitively, but pinning helps):

composer require padam87/money-bundle brick/money

Register it (Symfony Flex does not auto-register this bundle — it is not a Flex recipe):

// config/bundles.php
return [
    // ...
    Padam87\MoneyBundle\Padam87MoneyBundle::class => ['all' => true],
];

Where to look first, in order:

  1. README.md — the only real usage docs. Read it fully; it is short, and the v0.6.0 rewrite to brick/money changes the primary API surface.
  2. DependencyInjection/Configuration.php — the authoritative list of config keys (default_currency, decimal/precision options, etc.).
  3. Resources/config/ (or config/) — service IDs and tags. This is where you discover the Doctrine type name (usually money), the form type alias, and the Twig extension.
  4. Form/, Doctrine/ (or DBAL/Types/), Twig/ — the three integration surfaces you will actually use day-to-day.

Minimal config:

# config/packages/padam87_money.yaml
padam87_money:
    currency: EUR          # verify the exact key in Configuration.php
    # precision/scale if exposed

First use case — persist a price and render it:

use Brick\Money\Money;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
class Product
{
    #[ORM\Column(type: 'money')]          // bundle-provided DBAL type
    private Money $price;
}
{{ product.price|money }}   {# uses bundle Twig extension; check filter name #}

If the filter/form-type/DBAL type names differ in your installed version, bin/console debug:container --tag=twig.extension and bin/console debug:container --tag=form.type will list exactly what was registered.

Implementation Patterns

Doctrine type as the primary integration point. Treat the bundle mainly as a DBAL type provider. Persist Brick\Money\Money directly on the entity and let the type convert to/from the database. Unlike moneyphp, brick/money Money embeds its currency intrinsically — verify how the bundled type serialises the currency: it may store both amount and currency in a single column (e.g. "10.00 EUR"), or expect a separate currency column. Read convertToDatabaseValue/convertToPHPValue before assuming either layout.

Multi-currency. Because Money now carries its currency, the natural pattern is one column per price:

#[ORM\Column(type: 'money')]
private Money $price;

…but if the bundled type only persists the numeric amount, fall back to storing currency separately and reconstruct one of:

Money::of('10.00', 'EUR');            // major units (decimal string), DefaultContext
Money::ofMinor(1000, 'EUR');          // minor units (int), same result
Money::of('10.00', 'EUR', new CustomContext(scale: 2));  // explicit scale/context

Forms. Use the bundle's money form type (compound amount + currency) or wrap with a DataTransformer so the form still binds a single Money object:

$builder->add('price', MoneyType::class, [
    'currency' => 'EUR',        // important: do not rely on the global default in forms
    'divisor'  => 100,          // if supported — converts user input to minor units
]);

Twig formatting. Prefer the bundle extension over hand-rolled number_format. Note that brick/money does not ship a formatter (unlike moneyphp's MoneyFormatter), so any formatting service the bundle exposes is either a thin wrapper around NumberFormatter or its own implementation — check Resources/config/ to confirm the service ID and whether it honours the currency's subunit (JPY = 0, BHD = 3) before relying on it.

Service-level usage. Inject Brick\Money\Money factories or the bundle's money formatter directly into services. Keep arithmetic in Money objects and convert to a display string only at the edge:

$total = Money::total(...$lineItems);          // sum a list of Monies (was Money::sum)
$withTax = $total->multipliedBy('1.20');       // string/BigNumber multiplier, not float
$formatted = $this->moneyFormatter->format($total);  // bundle-wired formatter service

Arithmetic operations (plus, minus, multipliedBy, dividedBy, allocatedTo) return new instances and enforce context compatibility (see Gotchas).

Serialization. Brick\Money\Money implements JsonSerializable and emits ['amount' => '10.00', 'currency' => 'USD'] — a decimal string in major units, not minor units. Either accept that shape, or add a normalizer that converts to minor units for ledger-style APIs; either way, document the unit and precision in your OpenAPI spec.

Testing. Build fixtures with Money::of('10.00', 'EUR') or Money::ofMinor(1000, 'EUR') and assert against formatted strings. Use Money::total(...) in expectations rather than computing with intval — the BigNumber scale and context on both sides must match.

Gotchas and Tips

  • v0.6.0 is a hard-breaking refactor: moneyphp/money → brick/money. Any existing code that imports Money\Money, Money\Currency, or calls Money::sum(), Money::EUR() (moneyphp's signature), or uses MoneyFormatter will break. Migrate imports to Brick\Money\Money / Brick\Money\Currency, and swap Money::sum(...) for Money::total(...). Pin to ^0.6 and read every PR between 0.5.1 and 0.6.0 before touching a production branch.
  • Minor vs major units is now method-dependent. Money::ofMinor(1000, 'USD') is $10.00; Money::of('10.00', 'USD') is also $10.00; Money::of('1000', 'USD') is $1,000.00. This is the #1 source of bugs in brick/money because there is no single "amount" constructor. Verify what the bundle's form type produces and what the DBAL type writes before trusting either.
  • Contexts must match for arithmetic. plus()/minus() throw MoneyMismatchException if the two operands use different contexts (DefaultContext vs CashContext vs CustomContext). All Monies in one column/field must be constructed with the same context — set that at the DBAL type/hydrator, not scattered across services.
  • getAmount() returns a BigNumber, not an int. $money->getAmount() gives you a decimal string (e.g. '10.00'). Use (string) or getAmount()->toBigDecimal() — do not hand it to functions expecting an integer. getMinorAmount() / getUnscaledAmount() return BigNumber too, so cast them for integer storage.
  • Currency is intrinsic to Money now. Check whether the bundled DBAL type persists it (single combined column) or requires a companion currency column. A Money cannot be hydrated from amount alone, so a type that writes only the numeric amount will silently lose currency on read.
  • Never store money as a float or DECIMAL without understanding the type. The DBAL type should write a DECIMAL/VARCHAR (brick/money's default) or an integer (minor units, with an explicit context). If you see 10.0 where you expected 1000, check whether the writer used major or minor units.
  • Nullable prices break the type. Money is not nullable. Either make the property ?Money with a nullable-aware type wrapper, or guard in setters. A NULL column will throw on hydration.
  • The bundle is very small (≈4 stars, 0 dependents). Treat the source as the documentation. The v0.6.0 breaking change is a reminder: pin the version in composer.json and read the changelog before upgrading; API surface is not battle-tested across Symfony majors.
  • Locale in Twig is request-derived. In console commands, Messenger workers, and email rendering there is no Locale in the request stack — pass one explicitly or your output will fall back and be wrong for non-en currencies. This matters more now that brick/money has no shipped formatter to fall back on.
  • Debugging checklist:
    • bin/console debug:config padam87_money — confirm your config is picked up (and the key names are right).
    • bin/console debug:container --tag=doctrine.dbal.types — confirm the money type is registered and points at the Brick\Money implementation, not the legacy moneyphp one.
    • bin/console doctrine:schema:validate — catches type/column mismatches early.
    • bin/console debug:twig — confirm the extension and filter names.
  • Extension points: decorate the formatter service rather than reimplementing formatting; override the form type's Twig block ({% block money_widget %}) for custom UI; register your own DBAL type (backed by brick/money) if you need multi-currency or a specific context (e.g. CashContext(5) for CHF) instead of fighting the bundled one.
  • Padam87\MoneyBundle is not auto-registered. A fresh clone on a new machine will produce "class not found" for the type if you forgot config/bundles.php. This bites CI setups that don't run Flex recipes — and doubly so after v0.6.0, since any stale moneyphp/money still in the lockfile will mask the breakage until a clean install.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect