Product Decisions This Supports
- Financial Accuracy as a Core Feature: Adopting this package directly addresses precision requirements for monetary operations, aligning with product goals for trust, compliance, and error-free transactions (e.g., subscriptions, payments, or invoicing).
- Scalability for Multi-Currency: Enables seamless support for international markets without custom logic, reducing technical debt for future expansion (e.g., regional pricing, cross-border payments).
- Validation-Driven UX: Integrates
ValidMoney to enforce business rules (e.g., "prices must be ≥ $0" or "max $1000 for trials"), improving data quality and reducing support costs.
- Build vs. Buy Decision: Justifies adopting a maintained, standards-compliant library over custom implementations, freeing engineering resources for differentiation (e.g., unique payment flows).
- Roadmap Priorities:
- Phase 1: Replace floating-point fields in core models (e.g.,
Order, Subscription) with MoneyCast.
- Phase 2: Add currency conversion for global users (extend with a service like ExchangeRate-API).
- Phase 3: Audit logs for financial changes using immutable
Money objects.
- Use Cases:
- SaaS: Tiered pricing, prorated cancellations, and tax calculations.
- Marketplaces: Dynamic fees, payouts, and multi-vendor currencies.
- Fintech: Loan calculations, interest accruals, and compliance reporting.
When to Consider This Package
-
Adopt When:
- Your app processes high-value transactions (e.g., >$1K) where precision errors could cause financial loss or customer disputes.
- You need multi-currency support with validation (e.g., "EUR 100.50" vs. "USD 110.00").
- Your team prioritizes immutable data and type safety over dynamic casting (e.g., avoiding
float fields).
- You’re using Laravel 10–12 and want to avoid reinventing financial primitives.
- Your roadmap includes auditability (e.g., tracking changes to monetary values) or compliance (e.g., PCI DSS, GDPR for financial data).
-
Look Elsewhere If:
- Your use case involves simple arithmetic (e.g., basic discounts) where floating-point errors are negligible.
- You’re constrained by legacy systems using a different monetary library (e.g.,
moneyphp/money).
- Your team lacks PHP/Laravel expertise to configure database schemas or integrate new packages.
- You need real-time currency conversion (consider a dedicated service like CurrencyLayer).
- Your project is highly experimental and may pivot away from Laravel/PHP.
How to Pitch It (Stakeholders)
For Executives:
"This package eliminates a hidden risk in our financial systems: floating-point errors. For example, a $100.30 charge might incorrectly calculate as $100.29 due to PHP’s float limitations, leading to customer disputes or revenue loss. By adopting elegantly/laravel-money, we:
- Guarantee precision for all monetary operations (e.g., subscriptions, payments, invoices) using
Brick/Money, a library designed for financial accuracy.
- Future-proof our global expansion with built-in multi-currency support and validation, reducing rework as we enter new markets.
- Cut technical debt by replacing custom monetary logic with a maintained, MIT-licensed solution—similar to how we standardized on Laravel for our backend.
The upfront cost (schema updates, validation tweaks) is offset by immediate gains in accuracy, compliance, and developer productivity. It’s a low-risk investment with high ROI."
For Engineering Teams:
"This package integrates Brick/Money into Laravel with zero trade-offs:
- Database: Store amounts as
bigInteger (e.g., 10000 = $100.00) to eliminate floating-point errors.
- Models: Use
MoneyCast to automatically convert fields to immutable Money objects (e.g., $order->total->add($tax)).
- Validation: Enforce business rules with
ValidMoney (e.g., min: 0, max: 1000) in forms, APIs, or Livewire.
- Compatibility: Works with Laravel 10–12 and includes out-of-the-box support for Livewire/Form Requests.
Example migration:
Schema::create('orders', function (Blueprint $table) {
$table->bigInteger('amount'); // Stores 10000 = $100.00
$table->string('currency', 3); // 'USD', 'EUR', etc.
});
Then cast in your model:
protected $casts = [
'amount' => MoneyCast::of('currency'), // Dynamic currency
'tax' => MoneyCast::of('USD'), // Fixed currency
];
Key benefits: no more bcmath hacks, cleaner code, and built-in safety for financial data."
For Developers:
"Why this package beats custom solutions:
- Precision: Avoids floating-point pitfalls (e.g.,
0.1 + 0.2 !== 0.3).
- Safety:
ValidMoney catches invalid inputs early (e.g., negative prices, malformed currency codes).
- Flexibility: Supports dynamic or fixed currencies, and integrates with Livewire/Form Requests.
- Future-proof: Easy to extend for features like currency conversion or audit logs.
Example use cases:
// Parse user input safely
$amount = MoneyParser::parse($request->input('price'), 'USD');
// Validate in a Form Request
public function rules() {
return [
'price' => ['required', new ValidMoney(min: 0, max: 1000)],
];
}
// Cast model attributes
class Order extends Model {
protected $casts = [
'subtotal' => MoneyCast::of('currency'),
'tax' => MoneyCast::of('USD'),
];
}
Drop-in replacement for float fields—just update your schema and casts!"