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

gerardojbaez/money

A Laravel package for working with monetary values through an expressive API. It simplifies formatting, parsing, and converting currencies, making it easy to display prices and handle money safely in PHP code and Blade templates.

Deep Wiki
Context7

Getting Started

composer require gerardojbaez/money

Laravel will auto-discover the service provider on supported versions. If you are on an older Laravel, register Gerardojbaez\Money\MoneyServiceProvider manually. Publish the config so you can edit currency symbols, decimal places, separators, and format order:

php artisan vendor:publish --provider="Gerardojbaez\Money\MoneyServiceProvider"

Look first at:

  • config/money.php — the 91-entry currency table; this is where symbol, format, decimal places, thousands separator, and decimal mark live.
  • src/Money.php — the value object and format() implementation.
  • src/Currency.php — how a currency code is resolved and what happens when it is not in the table.

The simplest first use case is replacing number_format()/money_format() calls in a Blade view or API response:

use Gerardojbaez\Money\Money;

echo (new Money(1299.99, 'USD'))->format();   // $1,299.99

echo (new Money(49999, 'INR'))->format();    // ₹49,999.00 (symbol per config)

Amount plus ISO code in, formatted display string out. That is the core loop.

Implementation Patterns

Format at the edge, store raw values. Keep amount (integer minor units or a decimal string) and currency (ISO 4217 code) in the database. Instantiate Money only in presenters, Blade components, API resources, or mail templates. Never persist the formatted output — the archived currency table will eventually be wrong for some currency and you will want to change formatting without a data migration.

Wrap it in one application-level formatter. Rather than sprinkling new Money(...) everywhere, centralize it:

final class MoneyFormatter
{
    public function format($amount, string $currency, ?string $locale = null): string
    {
        return (new Money($amount, $currency))->format();
    }
}

This gives you one place to swap in intl/NumberFormatter later, or to add per-tenant formatting overrides. It also keeps the package's API surface out of your domain code.

Use it in Blade via a component or directive. A small Blade component keeps templates readable and makes the escaping story explicit:

<x-money :amount="$order->total" :currency="$order->currency" />

Return both raw and formatted values from APIs. Consumers often need the machine-readable value for calculations and the display string for UI:

return [
    'total' => $order->total,
    'currency' => $order->currency,
    'total_formatted' => (new Money($order->total, $order->currency))->format(),
];

Override currency metadata in config instead of subclassing. For a currency where the shipped config does not match your business rules — for example forcing zero decimals on a display-only currency, or changing the INR symbol from ₹ to Rs. — edit the relevant entry in config/money.php. This is the intended extension point and avoids forking Money for cosmetic changes.

Test against fixed expectations. Because the package is locale-independent by design, formatted output is deterministic. Assert exact strings in feature tests; this catches accidental config changes and makes upgrades safe:

$this->assertSame('$1,234.56', (new Money(1234.56, 'USD'))->format());

Delegate math to your own layer. Use the package only for rendering. Summing, tax calculation, rounding policy, and currency conversion should happen in domain code using integers or bcmath. Treat Money as a presenter, not an accounting primitive.

Gotchas and Tips

  • Archived in 2018. Pin the version in composer.json and consider vendoring or forking. Do not expect fixes for PHP 8.x deprecations, newer Laravel versions, or missing currencies. The package is small enough that a fork is realistic if you need changes.
  • format() is deliberately simple. It does not implement the full money_format() spec — no locale-driven negative parentheses, no full %n semantics. If you need accounting-style negatives or locale-aware grouping, use NumberFormatter from ext-intl and keep this package only for the simple cases.
  • Float input is a trap. Passing a PHP float into the constructor can produce surprising rounding for values like 1.005. Pass pre-rounded values, integer minor units divided at the boundary, or decimal strings. The formatter is not a rounding engine.
  • Missing currency behavior is not obvious. Check src/Currency.php to see whether an unknown ISO code throws, silently falls back, or formats without a symbol. Guard currency codes at validation time so bad data does not reach the formatter.
  • Config cache will confuse you. After publishing or editing config/money.php, run php artisan config:clear locally and php artisan config:cache in deploy. A stale cached config is the most common reason a symbol change “does not apply.”
  • Decimal places are per-currency, not per-call. If you need a one-off two-decimal rendering of a three-decimal currency, the package does not give you a clean override. Do it in your wrapper by temporarily setting config, or format manually.
  • INR rendering is a frontend concern too. The rupee symbol depends on the font available in PDFs and emails. Test PDF generation (DomPDF, Snappy) separately — a correct string can still render as a missing glyph.
  • Negatives are just string-concatenated. Verify how -1234.56 renders in your configured format before shipping invoice templates; do not assume parentheses or a sign position.
  • Laravel auto-discovery fails silently on older skeletons. If Money is not resolvable, check config/app.php providers/aliases before debugging the package itself.
  • Extension point for real customization is the formatter wrapper, not the package. If requirements grow beyond what config/money.php allows — multi-currency rounding rules, per-locale grouping, symbol placement by context — replace the internals of your MoneyFormatter with intl while keeping the call sites stable.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package