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

Laracash Laravel Package

andriichuk/laracash

Laracash is a Laravel package for working with money and currencies. It provides simple helpers for formatting, converting, and calculating monetary values, with configurable currency support for consistent cash handling across Laravel applications.

View on GitHub
Deep Wiki
Context7

Getting Started

andriichuk/laracash is a thin, Laravel-flavored wrapper around moneyphp/money. You get a money() helper, formatters, casters, Eloquent casts, and Blade helpers on top of an immutable Money value object.

Minimal setup:

composer require andriichuk/laracash
php artisan vendor:publish --tag=laracash-config   # optional but recommended

The service provider is auto-discovered. Open config/laracash.php first — it defines default_currency, default_formatter, and the formatters / casters maps. Almost everything you'll want to change lives there or is overridden per-call.

First use case — formatting a stored amount:

money(1999, 'USD')->format();          // "$19.99"
money(1999, 'USD', 'decimal')->format(); // "19.99"

If your first instinct is Money::USD(1999), that works too — laracash re-exports the underlying Money class. The helper just applies your configured default formatter and currency.

Implementation Patterns

Store minor units, format at the edges. Persist amounts as integer minor units (BIGINT) and never as DECIMAL or FLOAT. money(1999, 'USD') means 1999 cents. Mixing this with a decimal:2 cast is the #1 source of 100x bugs.

Eloquent casts for model attributes. The package ships a Andriichuk\Laracash\Casts\MoneyCast that takes the currency as a parameter:

protected $casts = [
    'price'    => MoneyCast::class.':USD',
    'shipping' => MoneyCast::class.':EUR',
];

$order->price now returns a Money instance; assigning an integer or a formatted string back to it runs through the configured caster.

Per-attribute currency. Don't rely on default_currency for models that can hold multiple currencies. Pass the currency explicitly on the cast, or store it as a sibling column and hydrate the Money object manually in an accessor:

public function getTotalAttribute(): Money
{
    return money($this->total_minor, $this->currency_code);
}

Blade: keep formatting out of controllers. Use the package's directive/component for view-level rendering:

@money($order->total_minor, 'USD')

This centralizes locale and formatter choice so a currency-formatting change ships in one place.

Format for output only. In JSON APIs, decide deliberately: return {"amount": 1999, "currency": "USD"} (raw, safe for clients) or {"formatted": "$19.99"} (server-rendered). Don't let a Money object hit json_encode — you'll either get an empty object or an exception depending on the underlying lib version.

Custom formatters and casters are the intended extension point. Register a class implementing the formatter/caster contract under a key in config/laracash.php, then reference it by name:

money(1999, 'USD', 'my_formatter')->format();

This is how you swap intl for a lightweight formatter on environments without ext-intl, or add a caster that parses "1.999,00" (EU format) from an import.

Testing. Assert on the integer minor units in the database, not on the formatted string. Formatter output is locale- and ICU-version-dependent and will flake across CI images.

Gotchas and Tips

  • No exchange-rate handling. laracash formats and casts; it does not convert. If you need EUR↔USD conversion, bring moneyphp/money's converters or your own rate table — do not expect money(1000, 'USD')->convertTo('EUR') to consult an API.
  • ext-intl is a soft requirement. The default intl formatter needs ICU. On stripped Alpine/Docker images you'll get a Class 'NumberFormatter' not found. Either install ext-intl or configure the decimal formatter as default.
  • Formatter locale ≠ app locale. NumberFormatter uses its own locale. If your app locale is de_DE but the formatter defaults to en_US, output silently uses $1,234.56 instead of 1.234,56 €. Pass an explicit locale or set it in the config.
  • Integer overflow. Money stores amounts as strings internally in moneyphp, but if you round-trip through a PHP int column make sure it's BIGINT. INT overflows around $21M in cents.
  • Immutability. Money methods (add, multiply, negative) return new instances. $money->multiply(3); does nothing. Always assign.
  • Rounding mode matters. ->multiply(0.1) on a taxable amount uses the underlying lib's default rounding (half-up). For financial reporting, pass the rounding mode explicitly and document it — the default can drift by a cent across versions.
  • Config caching. If you're using config:cache in CI/CD, publish and edit the config before the cache build. Editing config/laracash.php after config:cache has no effect until you re-cache.
  • Blade directive registration is done by the package's service provider. If you conditionally load providers or run in a non-standard environment (e.g., a package that renders Blade outside Laravel's provider boot), @money won't resolve — fall back to money(...)->format() in that context.
  • Currency code validation. Invalid ISO codes throw from the underlying Money library, not from laracash. Validate currency against Money::getCurrencies() or your own enum before constructing, especially when it comes from user input.
  • Serialization. If you must serialize a Money to JSON, add an explicit jsonSerialize() in a wrapper or cast to (string) first. Don't rely on default object serialization.
  • Where to look when it breaks: start with vendor/andriichuk/laracash/config/laracash.php (published copy) and src/Formatters / src/Casters. The whole package is a few hundred lines — reading the source is faster than hunting docs for edge cases.
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