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 Php Laravel Package

99designs/money-php

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require 99designs/money-php
    

    Add to composer.json if not using autoloading:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Money\\": "vendor/99designs/money/src/"
        }
    }
    
  2. First Use Case: Creating a Money Object

    use Money\Money;
    use Money\Currency;
    
    $amount = 100; // Amount in smallest currency unit (e.g., cents for USD)
    $currency = new Currency('USD');
    
    $money = new Money($amount, $currency);
    
  3. Where to Look First

    • README for basic usage.
    • src/Money/ directory for core classes (Money, Currency, Formatter).
    • tests/ for edge cases and examples.

Implementation Patterns

Core Workflows

  1. Money Creation and Manipulation

    $usd = new Money(1000, new Currency('USD')); // $10.00
    $eur = new Money(900, new Currency('EUR'));  // €9.00
    
    // Addition
    $total = $usd->add($eur);
    
    // Subtraction
    $change = $usd->subtract($eur);
    
    // Multiplication/Division (returns integer amount)
    $half = $usd->divideBy(2);
    $doubled = $usd->multiplyBy(2);
    
  2. Currency Conversion Requires a CurrencyConverter (e.g., from moneyphp/money-bundle or custom implementation).

    use Money\Converter\CurrencyConverter;
    
    $converter = new CustomCurrencyConverter(); // Implement CurrencyConverterInterface
    $converted = $converter->convert($usd, new Currency('EUR'));
    
  3. Formatting for Display

    use Money\Formatter\IntlMoneyFormatter;
    
    $formatter = new IntlMoneyFormatter('en_US');
    echo $formatter->format($usd); // "$10.00"
    
  4. Validation and Constraints

    use Money\Constraints\PositiveMoney;
    
    $validator = new PositiveMoney();
    $validator->validate($usd); // Throws \Money\Exception\InvalidMoneyException if invalid
    

Integration Tips

  • Database Storage: Store amount (integer) and currency (string) separately.
    // Migration
    Schema::create('orders', function (Blueprint $table) {
        $table->integer('amount');
        $table->string('currency', 3);
    });
    
    // Model
    public function getMoneyAttribute() {
        return new Money($this->amount, new Currency($this->currency));
    }
    
  • API Responses: Use Money objects in JSON responses with a custom JSON encoder or formatter.
  • Laravel Service Provider: Bind interfaces for easy mocking in tests.
    $this->app->bind(
        Money\Converter\CurrencyConverterInterface::class,
        CustomCurrencyConverter::class
    );
    

Gotchas and Tips

Pitfalls

  1. Precision Loss

    • Always work in the smallest currency unit (e.g., cents for USD) to avoid floating-point errors.
    • Avoid direct arithmetic with float/double values.
  2. Currency Codes

    • Use ISO 4217 currency codes (e.g., USD, EUR). Invalid codes throw exceptions.
    • Example of invalid code:
      new Currency('US'); // Throws \Money\Exception\InvalidCurrencyCodeException
      
  3. Immutable Objects

    • Money objects are immutable. Use methods like add()/subtract() to create new instances.
    • Avoid direct property manipulation (e.g., $money->amount = 200;).
  4. Converter Dependencies

    • The library does not include a converter. You must implement CurrencyConverterInterface or use a bundle like moneyphp/money-bundle.
  5. Negative Amounts

    • By default, Money allows negative amounts. Use PositiveMoney constraint to enforce positivity:
      $validator = new PositiveMoney();
      $validator->validate($money); // Throws if amount < 0
      

Debugging Tips

  • Assertions: Use assertEquals for testing:
    use PHPUnit\Framework\TestCase;
    
    $this->assertEquals(
        new Money(1000, new Currency('USD')),
        $usd->add(new Money(0, new Currency('USD')))
    );
    
  • Logging: Log raw amount and currency for debugging:
    \Log::debug("Money amount: {$money->getAmount()}, currency: {$money->getCurrency()->getCode()}");
    

Extension Points

  1. Custom Formatters Extend Money\Formatter\MoneyFormatterInterface for locale-specific formatting:

    class CustomFormatter implements MoneyFormatterInterface {
        public function format(Money $money) {
            return sprintf('%s %s', $money->getAmount() / 100, $money->getCurrency()->getCode());
        }
    }
    
  2. Custom Constraints Implement Money\Constraints\MoneyConstraintInterface for business rules:

    class MaxOrderConstraint implements MoneyConstraintInterface {
        public function validate(Money $money) {
            if ($money->getAmount() > 100000) {
                throw new \RuntimeException('Order exceeds maximum allowed amount.');
            }
        }
    }
    
  3. Custom CurrencyConverter Implement Money\Converter\CurrencyConverterInterface for exchange rates:

    class ApiCurrencyConverter implements CurrencyConverterInterface {
        public function convert(Money $money, Currency $toCurrency) {
            $rate = $this->fetchRate($money->getCurrency(), $toCurrency);
            return new Money(
                (int) round($money->getAmount() * $rate),
                $toCurrency
            );
        }
    }
    
  4. Laravel Integration

    • Use accessors/mutators in Eloquent models:
      public function getPriceAttribute() {
          return new Money($this->amount, new Currency($this->currency));
      }
      
      public function setPriceAttribute($value) {
          $this->amount = $value->getAmount();
          $this->currency = $value->getCurrency()->getCode();
      }
      
    • Middleware for currency-aware routes:
      public function handle($request, Closure $next) {
          $request->merge(['currency' => 'EUR']);
          return $next($request);
      }
      
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
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