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

Immutable money & currency library for PHP with exact arithmetic, explicit rounding control, and support for any-sized amounts. Built on brick/math to avoid floating-point errors; works with ISO currencies and integrates well with GMP/BCMath for speed.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Precision-Critical Domain: Brick\Money excels in financial applications requiring exact arithmetic (e.g., invoicing, accounting, or e-commerce). Its immutable design and support for arbitrary-precision calculations (via GMP/BCMath) mitigate floating-point errors inherent in PHP’s native float.
  • Laravel Synergy: Aligns with Laravel’s dependency injection (DI) and service container patterns. The package’s stateless, pure-functional approach avoids side effects, making it ideal for domain-driven design (DDD) layers.
  • Contextual Flexibility: Supports custom contexts (e.g., CashContext for Swiss Franc rounding rules), enabling compliance with region-specific financial regulations.

Integration Feasibility

  • Composer Integration: Zero friction—install via composer require brick/money. No global state or configuration required.
  • Laravel Ecosystem Compatibility:
    • Eloquent Models: Can be used as model attributes (e.g., protected $price;) with accessors/mutators for serialization/deserialization.
    • API Responses: Serializable to JSON via JsonSerializable or custom encoders (e.g., Money::getAmount() + Money::getCurrency()).
    • Queues/Jobs: Immutable objects are thread-safe for background processing (e.g., order fulfillment).
  • Database Storage:
    • Minor Units: Store as integers (e.g., 999 for $9.99 USD) to avoid precision loss.
    • Currency Codes: Store as CHAR(3) (ISO 4217) or INTEGER (numeric codes).
    • Context: Serialize context parameters (e.g., step for CashContext) as JSON or separate columns.

Technical Risk

  • Breaking Changes: Pre-1.0 releases may introduce breaking changes (e.g., currency updates). Mitigate by pinning to a minor version (e.g., 0.13.*).
  • Performance Overhead:
    • GMP/BCMath: Required for large-scale calculations (e.g., batch processing). Benchmark against PHP’s native bcmath for critical paths.
    • RationalMoney: Use sparingly—intermediate fractions consume more memory.
  • Currency Updates: ISO 4217 changes (e.g., new currencies) may require schema migrations if storing currency codes directly.
  • Legacy PHP: Requires PHP 8.2+. If using older versions, downgrade to 0.10 (PHP 8.1) or 0.8 (PHP 8.0), but note EOL risks.

Key Questions

  1. Precision Requirements:
    • Are floating-point errors (e.g., 0.1 + 0.2 = 0.30000000000000004) acceptable in your domain?
    • Do you need support for arbitrary-precision calculations (e.g., cryptocurrency, scientific finance)?
  2. Context Needs:
    • Do you require custom rounding rules (e.g., CashContext for CHF) or dynamic scaling (e.g., AutoContext)?
  3. Database Schema:
    • Will you store Money as minor units + currency code, or serialize the entire object?
    • How will you handle context serialization (e.g., CashContext with step=5)?
  4. Performance:
    • Will you use GMP/BCMath, or accept slower native PHP arithmetic for non-critical paths?
    • Are there batch operations (e.g., splitting 1M orders) where RationalMoney could cause memory issues?
  5. Testing:
    • How will you test edge cases (e.g., rounding modes, currency mismatches, large numbers)?
    • Will you mock Money in unit tests, or use a test double library (e.g., mocks-for-php)?

Integration Approach

Stack Fit

  • Laravel Core:
    • Request/Response: Use Money objects in DTOs (e.g., CreateOrderRequest with Money $amount).
    • Validation: Leverage Laravel’s validation rules to enforce currency codes and rounding modes.
    • API Resources: Transform Money to JSON via JsonSerializable or custom accessors.
  • Database:
    • MySQL/PostgreSQL: Store minor units as DECIMAL or BIGINT (e.g., amount_minor INT, currency CHAR(3)).
    • MongoDB: Store as embedded documents (e.g., { amount: 999, currency: "USD", context: { type: "default" } }).
  • Caching:
    • Redis: Serialize Money objects using igbinary or json_encode for caching order totals.
    • Currency Rates: Cache exchange rates separately (e.g., brick/math for conversions).

Migration Path

  1. Phase 1: Core Domain
    • Replace primitive float/int amounts with Money in domain models (e.g., Order, Invoice).
    • Example:
      // Before
      public function calculateTotal(): float { return $this->items->sum('price'); }
      
      // After
      public function calculateTotal(): Money {
          return $this->items->reduce(
              fn (Money $carry, Item $item) => $carry->plus($item->getPrice()),
              Money::zero('USD')
          );
      }
      
  2. Phase 2: API Layer
    • Update API responses to return Money objects (e.g., GET /orders/{id}{ "total": { "amount": 999, "currency": "USD" } }).
    • Use Laravel’s JsonResponse with custom encoders if needed.
  3. Phase 3: Database
    • Add migration to store minor units + currency:
      Schema::table('orders', function (Blueprint $table) {
          $table->unsignedBigInteger('total_amount_minor')->default(0);
          $table->char('currency', 3)->default('USD');
      });
      
    • Backfill existing data using Money::ofMinor().
  4. Phase 4: Legacy Support
    • Create facade methods to wrap legacy float operations (e.g., LegacyMoney::fromFloat(19.99, 'USD')).

Compatibility

  • Laravel Services:
    • Queue Jobs: Money is serializable via serialize() (PHP’s native mechanism) or JsonSerializable.
    • Events: Dispatch events with Money payloads (e.g., OrderCreated with Money $amount).
    • Notifications: Use Money in notification data (e.g., OrderPaid email with formatted amount).
  • Third-Party Libraries:
    • Laravel Cashier: Replace float amounts with Money in subscription logic.
    • Laravel Scout: Index Money fields for search (e.g., filter orders by price range).
    • Laravel Horizon: Process queue jobs with Money payloads (ensure serialization works).

Sequencing

  1. Start with Non-Critical Paths:
    • Begin with read-only operations (e.g., displaying prices) before modifying write paths (e.g., order creation).
  2. Test Edge Cases Early:
    • Validate rounding modes, currency mismatches, and large numbers in CI.
  3. Incremental Rollout:
    • Use feature flags to toggle Money usage in specific modules (e.g., e-commerce vs. admin dashboard).
  4. Monitor Performance:
    • Profile Money operations in production (e.g., Xdebug, Blackfire) to identify GMP/BCMath bottlenecks.

Operational Impact

Maintenance

  • Dependencies:
    • Brick\Math: Core dependency for exact arithmetic. Monitor for breaking changes.
    • ISO 4217 Updates: Subscribe to ISO currency updates to proactively handle new currencies.
  • Versioning:
    • Pin to a minor version (e.g., 0.13.*) to avoid unexpected breaking changes.
    • Use composer why brick/money to audit dependencies.
  • Documentation:
    • Add internal docs for custom contexts (e.g., "Use CashContext for CHF with step=5").
    • Document rounding mode strategies (e.g., "Always use RoundingMode::Down for cashier drawer reconciliation").

Support

  • Common Issues:
    • Currency Mismatches: Log warnings when operations fail due to mismatched currencies (e.g., USD + EUR).
    • Rounding Necessary Exceptions: Provide user-friendly error messages (e.g., "Rounding required for $9.999 USD. Use RoundingMode::Up").
    • Serialization Errors: Ensure all Money objects are properly serialized/deserialized in queues or caches.
  • Debugging:
    • Use Money::getAmount() + Money::getCurrency() for logging/debugging.
    • Add custom error handlers for `
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests