akaunting/laravel-money

repository·master·Indexed 21 days ago

https://github.com/akaunting/laravel-money

A Laravel package for currency formatting and conversion that avoids reliance on the PHP intl extension. It provides the Money and Currency classes for arithmetic, comparisons, and state management, along with Eloquent casts (MoneyCast and CurrencyCast), custom validation rules for currency codes, and dedicated Blade directives and components for rendering monetary values.

Tokens
2.6K
Snippets
13
Records
14
Agent score
63%

What's inside laravel-money

  1. Extend Money and Currency with Macros and Mixins

    master

    Both Money and Currency implement the Macroable trait, allowing you to add custom functionality at runtime.

    Macros: Use Money::macro('name', callback) to add a new method. Macros can be called on instances or statically.

    Mixins: Use Money::mixin($instance) to merge all methods from a custom class into the Money class. This is useful for grouping related custom logic.

    Example using a Mixin:

    class CustomMoney {
        public function absolute(): Money {
            return $this->isPositive() ? $this : $this->multiply(-1);
        }
    }
    
    Money::mixin(new CustomMoney);
    $money = Money::USD(1000)->multiply(-1);
    echo $money->absolute();
    use Akaunting\Money\Money;
    
    // Registering a Macro
    Money::macro('zero', fn (?string $currency = null) => new Money(0, new Currency($currency ?? 'GBP')));
    $money = Money::zero();
  2. Install and configure laravel-money

    master

    To use this package in your Laravel project, install it via Composer, publish the configuration file, and customize your currency settings.

    1. Install the package:
      composer require akaunting/laravel-money
    2. Publish the configuration file:
      php artisan vendor:publish --tag=money
    3. Configure your application's currency information in config/money.php.
    composer require akaunting/laravel-money
    php artisan vendor:publish --tag=money
  3. Display Money and Currency in Blade templates

    master

    You can render monetary values directly in Blade views using directives or components.

    Blade Directives:

    • @money(amount, currency)
    • @currency(currency)

    Blade Components:

    • <x-money amount="500" />
    • <x-money amount="500" currency="USD" />
    • <x-money amount="500" currency="USD" convert />
    • <x-currency currency="USD" />
    {{-- Using Directives --}}
    @money(500, 'USD')
    
    {{-- Using Components --}}
    <x-money amount="500" currency="USD" convert />
  4. Create Money instances

    master

    You can create Money objects using static helper methods on the Money class or by instantiating the class directly. By default, values are unconverted. To enable conversion, pass true as the third argument to the constructor or the second argument to the static method.

    Use Akaunting\Money\Money for monetary values and Akaunting\Money\Currency to define the currency.

    use Akaunting\Money\Currency;
    use Akaunting\Money\Money;
    
    echo Money::USD(500); // '$5.00' unconverted
    echo new Money(500, new Currency('USD')); // '$5.00' unconverted
    echo Money::USD(500, true); // '$500.00' converted
    echo new Money(500, new Currency('USD'), true); // '$500.00' converted
  5. Perform arithmetic and comparisons with Money

    master

    The Money class provides a rich API for mathematical operations, comparisons, and conversions.

    Arithmetic:

    • add($money): Add another money instance.
    • subtract($money): Subtract another money instance.
    • multiply($factor): Multiply by a factor.
    • divide($factor): Divide by a factor.
    • allocate([$amounts]): Distribute the amount across an array of parts.

    Comparisons:

    • equals($money): Check if amounts and currencies are equal.
    • isSameCurrency($money): Check if currencies match.
    • compare($money): Compare two money instances.
    • greaterThan($money), greaterThanOrEqual($money), lessThan($money), lessThanOrEqual($money)

    State & Conversion:

    • convert(Currency $currency, $rate): Convert to a new currency using a specific rate.
    • isZero(), isPositive(), isNegative()
    • getCurrency(): Retrieve the current Currency object.
    • format(): Return the formatted string.
    $m1 = Money::USD(500);
    $m2 = Money::EUR(500);
    
    $m1->compare($m2);
    $m1->add($m2);
    $m1->convert(Currency::GBP(), 3.5);
    $m1->isZero();
  6. Use CurrencyCast to cast Eloquent attributes to Currency objects

    master

    The CurrencyCast class allows you to automatically convert database string values into Akaunting\Money\Currency objects when accessing Eloquent model attributes, and back into strings when saving them.

    To use it, add Akaunting\Money\Casts\CurrencyCast to the $casts property of your Laravel Eloquent model for the specific attribute key.

    Behavior:

    • Retrieval (get): Converts the database string value into a new Currency instance. Throws an UnexpectedValueException if the database value is not a string.
    • Storage (set): Expects an instance of Akaunting\Money\Currency. It calls $value->getCurrency() to retrieve the string representation for database storage. Throws an UnexpectedValueException if the value provided is not an instance of Currency.
    use Akaunting\Money\Casts\CurrencyCast;
    use Illuminate\Database\Eloquent\Model;
    
    class Product extends Model
    {
        protected $casts = [
            'price' => CurrencyCast::class,
        ];
    }
    
    // Usage:
    $product = Product::find(1);
    // $product->price is now an instance of Akaunting\Money\Currency
    
    $product->price = new \Akaunting\Money\Currency('USD 100.00');
    $product->save();
  7. Use Blade directives for money and currency

    master

    The package provides two Blade directives to quickly render formatted money or currency values in your templates:

    • @money($expression): Renders the value using the money() helper.
    • @currency($expression): Renders the value using the currency() helper.
    @money($amount)
    @currency($amount)
  8. Use the Money Blade component

    master

    The <x-money> Blade component allows you to display formatted money values directly in your Laravel Blade templates. It accepts an amount, an optional currency code, and an optional conversion flag.

    Attributes

    AttributeTypeDescription
    amountmixedThe monetary value to be formatted.
    currencystring (optional)The ISO currency code (e.g., USD, EUR).
    convertbool (optional)Whether to convert the amount to the current application currency.

    Note: The component renders the view money::components.money.

    <x-money :amount="$order->total" currency="USD" :convert="true" />
  9. Use the currency_code validation rule

    master
    The package registers a custom Laravel validation rule currency_code. This rule checks if the provided string exists within the list of currencies defined in your money.php configuration file. If the validation fails, it uses the translation key validation.custom.invalid_currency to generate the error message.
  10. Use MoneyCast to cast Eloquent attributes to Money objects

    master

    The MoneyCast class allows you to automatically convert database columns into Money objects using Laravel's Eloquent casting.

    When casting an attribute with MoneyCast:

    • Retrieval (get): The database value must be a JSON string containing an amount and a currency key (e.g., {"amount":100,"currency":"USD"}). The caster will return a new Akaunting\Money\Money instance.
    • Storage (set): When you assign a Money object to the attribute, the caster will automatically encode it into a JSON string for storage in the database, preserving the amount and the currency code.

    If the database value is not a valid JSON string containing both amount and currency, or if you attempt to set the attribute with a value that is not an instance of Money, an UnexpectedValueException will be thrown.

    use Akaunting\Money\Casts\MoneyCast;
    use Illuminate\Database\Eloquent\Model;
    
    class Product extends Model
    {
        protected $casts = [
            'price' => MoneyCast::class,
        ];
    }