Weave Code
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

brick/money

Brick\Money is a PHP library for precise, immutable money and currency values. It provides exact arithmetic (no float errors), explicit rounding control, and supports large amounts via brick/math, with optional GMP/BCMath acceleration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Precision & Financial Accuracy: The package excels in financial use cases where floating-point precision is critical (e.g., e-commerce, accounting, or payment systems). Its immutable design and exact arithmetic (via brick/math) align perfectly with Laravel’s need for reliable financial operations.
  • Laravel Integration: Laravel’s built-in Money facade (if used) or custom financial logic can leverage this package for consistency. The package’s context-based rounding (e.g., CashContext, AutoContext) addresses real-world currency constraints (e.g., Swiss Franc cash rounding).
  • Domain-Driven Design (DDD): The package’s money allocation (split(), allocate()) and comparison methods (isEqualTo(), isSameValueAs()) support DDD patterns like Value Objects and Domain Events (e.g., for order processing or tax calculations).

Integration Feasibility

  • Composer Compatibility: Zero friction—installs via composer require brick/money with no Laravel-specific dependencies.
  • PHP 8.2+ Requirement: Laravel 10+ (PHP 8.1+) or 11+ (PHP 8.2+) are compatible. For older Laravel versions, downgrade to 0.10 (PHP 8.1) or 0.8 (PHP 8.0).
  • Database Persistence: Requires serialization (e.g., Money::ofMinor() for storage) or custom accessors in Eloquent models. Example:
    // Model attribute casting
    protected $casts = [
        'amount' => Money::class,
    ];
    
  • API/Service Layer: Ideal for DTOs (Data Transfer Objects) or Value Objects in Laravel’s service layer. Example:
    class OrderTotal {
        public function __construct(public Money $amount) {}
    }
    

Technical Risk

  • Breaking Changes: Pre-1.0 releases may introduce minor version bumps for currency updates (e.g., ISO 4217). Lock to 0.x.* (e.g., 0.13.*) to mitigate risk.
  • Performance: Heavy calculations (e.g., RationalMoney chains) may impact latency. Benchmark with GMP/BCMath extensions enabled for optimization.
  • Currency Contexts: Custom contexts (e.g., CashContext) require upfront design decisions. Misconfiguration (e.g., wrong step for CHF) could lead to incorrect rounding.
  • Testing: Financial logic demands property-based testing (e.g., with PestPHP) to validate edge cases like:
    • Rounding modes (RoundingMode::Up vs. Down).
    • Cross-currency operations (should throw CurrencyMismatchException).

Key Questions

  1. Use Case Scope:
    • Is this for order processing, billing, or multi-currency support? Narrow the scope to justify the package’s complexity.
  2. Legacy Integration:
    • How will existing float/decimal fields in databases/models map to Money objects? Use accessors/mutators or database migrations.
  3. Rounding Strategy:
    • Should rounding default to RoundingMode::HalfUp (banker’s rounding) or Up (conservative)?
  4. Currency Flexibility:
    • Will the app support historical currencies (e.g., IsoCurrencyProvider::getHistoricalCurrenciesForCountry())?
  5. Performance:
    • Are there high-throughput operations (e.g., batch allocations) where RationalMoney could be optimized?

Integration Approach

Stack Fit

  • Laravel Ecosystem:
    • Eloquent Models: Use accessors to convert Money objects to/from database fields.
      // Model
      public function getAmountAttribute($value) {
          return Money::ofMinor($value, $this->currency);
      }
      
    • API Responses: Serialize Money to JSON via custom encoders or DTOs.
      // DTO
      public function toArray(): array {
          return ['amount' => $this->money->getAmount(), 'currency' => $this->money->getCurrencyCode()];
      }
      
    • Queues/Jobs: Pass Money objects directly in Laravel queues (immutability ensures thread safety).
  • Third-Party Services:
    • Payment Gateways (Stripe, PayPal): Convert Money to gateway-specific formats (e.g., Money::ofMinor() → cents).
    • Tax Calculators: Use MoneyBag for multi-currency tax splits.

Migration Path

  1. Phase 1: Core Financial Logic
    • Replace hardcoded float calculations with Money objects in domain services.
    • Example: Refactor OrderService to use Money::of() instead of floatval().
  2. Phase 2: Database Layer
    • Add amount (minor units) and currency columns to tables (e.g., orders, invoices).
    • Use model observers to sync Money objects with database fields.
  3. Phase 3: API/UI
    • Update API responses to include amount and currency fields.
    • Localize currency symbols in Blade templates using Money::getCurrencyCode().

Compatibility

  • Laravel Versions:
    • Laravel 10/11: Use 0.13.* (PHP 8.2+).
    • Laravel 9: Downgrade to 0.10 (PHP 8.1).
  • Database:
    • MySQL/PostgreSQL: Store minor units as DECIMAL(20, 0) (e.g., cents) to avoid floating-point issues.
    • SQLite: Use INTEGER for minor units.
  • Legacy Code:
    • Wrap existing float logic in adapters to gradually adopt Money:
      class FloatAdapter {
          public static function toMoney(float $amount, string $currency): Money {
              return Money::ofMinor(round($amount * 100), $currency);
          }
      }
      

Sequencing

  1. Proof of Concept:
    • Implement a single feature (e.g., order totals) with Money to validate the approach.
  2. Testing:
    • Write unit tests for critical paths (e.g., Money::allocate(), MoneyBag).
    • Test edge cases (e.g., rounding, currency mismatches).
  3. Incremental Rollout:
    • Start with read-only usage (e.g., displaying amounts).
    • Gradually enable write operations (e.g., creating orders).
  4. Monitoring:
    • Log Money-related operations to catch currency mismatches or rounding discrepancies early.

Operational Impact

Maintenance

  • Dependency Updates:
    • Pin to 0.x.* to avoid breaking changes. Monitor release notes for currency updates.
    • Use Composer scripts to automate version checks:
      {
        "scripts": {
          "check-money-version": "php -r \"$version = file_get_contents('composer.lock'); if (strpos($version, 'brick/money': '0.14') !== false) echo 'Warning: Major version bump detected!';\""
        }
      }
      
  • Currency Maintenance:
    • Schedule quarterly reviews to update ISO 4217 currencies (e.g., new cryptocurrencies, deprecated codes).
  • Documentation:
    • Add internal docs for:
      • Rounding strategies per currency.
      • Money object lifecycle (creation, operations, serialization).

Support

  • Debugging:
    • Currency Mismatch: Log CurrencyMismatchException with stack traces to identify integration issues.
    • Rounding Errors: Use RationalMoney for complex calculations to trace discrepancies.
  • Common Issues:
    • Time Zones: Ensure currency codes (e.g., USD) align with business logic (e.g., tax jurisdiction).
    • Localization: Cache Currency::getSymbol() to avoid repeated ISO lookups.
  • Support Matrix:
    Issue Type Resolution Path
    Rounding discrepancies Reproduce with RationalMoney
    Currency not found Check ISO 4217 updates
    Performance bottlenecks Enable GMP/BCMath, optimize contexts

Scaling

  • Performance:
    • Caching: Cache Currency objects (e.g., Currency::of('USD')) in a static container.
    • Batch Operations: Use MoneyBag for bulk calculations (e.g., refunds, payouts).
    • Database: Index currency columns for fast joins.
  • Horizontal Scaling:
    • **Stateless
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope