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

moneyphp/money

moneyphp/money is a PHP value-object library for safe money handling without floats. Uses string-based big integers, supports arithmetic, allocation, currencies/ISO repositories, formatting (incl. intl), JSON serialization, and exchange rates. Requires BCMath.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require moneyphp/money

Ensure bcmath extension is enabled in your PHP configuration.

  1. First Use Case: Create a Money object for a specific currency:

    use Money\Money;
    
    $amount = Money::EUR(500); // 5.00 EUR
    
  2. Key Classes to Know:

    • Money: Core value object for monetary amounts.
    • Currency: Represents currencies (e.g., Currency::EUR).
    • MoneyFactory: Static factory for creating Money objects.
    • Converter: Handles currency conversions.
  3. Where to Look First:

    • Official Documentation (API reference, examples).
    • src/Money/Money.php (core Money class).
    • src/Money/Currency.php (currency definitions).

Implementation Patterns

Core Workflows

1. Creating and Manipulating Money

  • Static Factory Methods:
    $fiveEur = Money::EUR(500); // 5.00 EUR (subunits)
    $tenUsd = Money::USD(1000); // 10.00 USD
    
  • Arithmetic Operations:
    $sum = $fiveEur->add($tenUsd); // Throws exception (currencies must match)
    $sumSameCurrency = $fiveEur->add(Money::EUR(300)); // 8.00 EUR
    
  • Division/Multiplication:
    $half = $fiveEur->divide('2'); // 2.50 EUR
    $double = $fiveEur->multiply('2'); // 10.00 EUR
    

2. Currency Conversion

  • Basic Conversion:
    $converter = new Money\Converter($exchangeRates);
    $converted = $converter->convert($fiveEur, Currency::USD);
    
  • Using Converter with Exchange Rates:
    $exchangeRates = [
        'EUR' => ['USD' => '1.10'], // 1 EUR = 1.10 USD
    ];
    $converter = new Money\Converter($exchangeRates);
    
  • Swap Exchange (for complex rates):
    use Money\Currency\ISOCurrencies;
    use Money\Exchange\Swap;
    
    $swap = new Swap(ISOCurrencies::getInstance());
    $rate = $swap->getRate('EUR', 'USD');
    

3. Formatting and Parsing

  • Formatting:
    $formatter = new Money\Formatter\IntlMoneyFormatter(
        'en_US',
        IntlMoneyFormatter::CURRENCY_FORMATTING
    );
    echo $formatter->format($fiveEur); // "$5.00"
    
  • Parsing:
    $parser = new Money\Parser\DecimalMoneyParser();
    $money = $parser->parse('5.00', Currency::USD);
    

4. Aggregations

$amounts = [Money::EUR(100), Money::EUR(200), Money::EUR(300)];
$sum = Money::sum($amounts); // 6.00 EUR
$avg = Money::avg($amounts); // 2.00 EUR

5. Allocation (Splitting Money)

$tenEur = Money::EUR(1000);
list($part1, $part2, $part3) = $tenEur->allocate([1, 1, 1]);
// part1: 3.34 EUR, part2: 3.33 EUR, part3: 3.33 EUR (due to rounding)

6. Working with Crypto-Currencies

use Money\Currency\CryptoCurrencies;

$bitcoin = Money::BTC('100000000'); // 1.00 BTC (subunits: satoshis)
$cryptoCurrencies = new CryptoCurrencies();
$ethereum = Money::ETH('500000000000000000', $cryptoCurrencies->get('ETH'));

Integration Tips

Laravel-Specific Patterns

  1. Service Container Binding: Bind MoneyFactory, Converter, or ISOCurrencies in AppServiceProvider:

    public function register()
    {
        $this->app->singleton(Money\Currency\ISOCurrencies::class, function () {
            return Money\Currency\ISOCurrencies::getInstance();
        });
    }
    
  2. Request Validation: Use moneyphp/money with Laravel's validation:

    use Money\Currency\ISOCurrencies;
    use Money\Parser\DecimalMoneyParser;
    
    $parser = new DecimalMoneyParser();
    $currency = ISOCurrencies::getInstance()->get('USD');
    
    $validated = request()->validate([
        'amount' => ['required', function ($attribute, $value, $fail) use ($parser, $currency) {
            try {
                $money = $parser->parse($value, $currency);
            } catch (\Exception $e) {
                $fail('Invalid monetary value.');
            }
        }],
    ]);
    
  3. Database Storage: Store Money objects as strings (e.g., "EUR:500") or use JSON serialization:

    $money = Money::EUR(500);
    $serialized = json_encode($money); // '{"amount":"500","currency":"EUR"}'
    $deserialized = Money::fromArray(json_decode($serialized, true));
    
  4. API Responses: Format Money objects in responses:

    return response()->json([
        'total' => (new Money\Formatter\DecimalMoneyFormatter())->format($totalMoney),
    ]);
    
  5. Testing: Use Money\Comparator for assertions:

    use Money\Comparator;
    
    $this->assertTrue(Comparator::equals($money1, $money2));
    

Gotchas and Tips

Pitfalls

  1. Floating-Point Avoidance:

    • Gotcha: Passing floats to Money methods (e.g., Money::EUR(5.5)) will throw an exception.
    • Fix: Use numeric strings or integers:
      $money = Money::EUR('5.50'); // Correct
      $money = Money::EUR(550);    // Correct (subunits)
      
  2. Currency Mismatches:

    • Gotcha: Arithmetic operations (add, subtract) require matching currencies. Mixing currencies throws an exception.
    • Fix: Convert currencies first using Converter:
      $converter = new Money\Converter($exchangeRates);
      $converted = $converter->convert($eurMoney, Currency::USD);
      
  3. Subunit Precision:

    • Gotcha: Some currencies (e.g., JPY) have no subunits (e.g., 1 subunit = 1 currency). Operations like divide may behave unexpectedly.
    • Fix: Use roundToUnit or handle edge cases:
      $yen = Money::JPY(100);
      $half = $yen->divide('2'); // 50 JPY (no fractional part)
      
  4. BCMath/GMP Dependencies:

    • Gotcha: The library defaults to BCMath for calculations. If BCMath is unavailable, operations may fail or fall back to slower methods.
    • Fix: Ensure bcmath is enabled in php.ini or configure a fallback calculator:
      $calculator = new Money\Calculator\GmpCalculator();
      $money = new Money\Money('1000', Currency::USD, $calculator);
      
  5. Negative Values:

    • Gotcha: Negative money values are allowed but may cause unexpected behavior in some operations (e.g., allocate).
    • Fix: Validate inputs or handle negatives explicitly:
      if ($money->isNegative()) {
          // Handle negative case
      }
      
  6. JSON Serialization:

    • Gotcha: Money objects serialize to arrays by default, which may not match your API expectations.
    • Fix: Use a custom formatter or implement JsonSerializable:
      $serialized = json_encode([
          'amount' => $money->getAmount(),
          'currency' => $money->getCurrency()->getCode(),
      ]);
      
  7. Currency Code Case:

    • **Got
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