# Laravel Money Laravel Money is a PHP package that provides seamless integration of the MoneyPHP library with Laravel applications. It offers a clean, fluent API for handling monetary values with proper currency support, avoiding common floating-point precision issues. The package supports all ISO currencies, Bitcoin currencies, and custom currencies while providing automatic locale-aware formatting. The library abstracts MoneyPHP to work naturally within Laravel's ecosystem, providing Eloquent model casting, validation rules, Blade directives, and global helper functions. It handles money amounts in minor units (cents) internally to maintain precision, supports arithmetic operations (add, subtract, multiply, divide), comparison methods, aggregation functions (min, max, avg, sum), and multiple parsing/formatting strategies for different use cases. ## Installation Install the package via Composer. ```bash composer require cknow/laravel-money ``` ## Configuration Publish and customize the configuration file for locale, default currency, and supported currencies. ```bash php artisan vendor:publish --provider="Cknow\Money\MoneyServiceProvider" ``` ```php // config/money.php return [ 'locale' => config('app.locale', 'en_US'), 'defaultCurrency' => config('app.currency', 'USD'), 'defaultFormatter' => null, 'defaultSerializer' => null, 'currencies' => [ 'iso' => 'all', // or ['USD', 'EUR', 'GBP'] for specific currencies 'bitcoin' => 'all', 'custom' => [ 'MY1' => 2, // custom currency with 2 decimal places 'MY2' => 3 ] ] ]; ``` ## Money::USD() - Currency Factory Methods Create Money instances using static currency code methods. The amount is specified in minor units (cents) by default. Use `forceDecimals = true` to treat the amount as a decimal value. ```php use Cknow\Money\Money; // Create $5.00 USD (500 cents) $price = Money::USD(500); echo $price; // Output: $5.00 // Create $500.00 USD with forceDecimals enabled $largePrice = Money::USD(500, true); echo $largePrice; // Output: $500.00 // Create amounts in other currencies $euros = Money::EUR(1500); // 15.00 $pounds = Money::GBP(2999); // 29.99 $yen = Money::JPY(1000); // 1,000 (no decimal places) $bitcoin = Money::XBT(41000000); // 0.41 BTC // Access internal values echo $price->getAmount(); // "500" echo $price->getCurrency()->getCode(); // "USD" ``` ## Arithmetic Operations Perform mathematical operations on Money objects. All operations return new Money instances and maintain currency consistency. ```php use Cknow\Money\Money; // Addition - single or multiple values $total = Money::USD(500)->add(Money::USD(500)); echo $total; // $10.00 $multiAdd = Money::USD(500)->add(Money::USD(500), Money::USD(500)); echo $multiAdd; // $15.00 // Subtraction $remaining = Money::USD(500)->subtract(Money::USD(400)); echo $remaining; // $1.00 $multiSubtract = Money::USD(500)->subtract(Money::USD(200), Money::USD(100)); echo $multiSubtract; // $2.00 // Multiplication $doubled = Money::USD(500)->multiply(2); echo $doubled; // $10.00 $scaled = Money::USD(100)->multiply(1.5); echo $scaled; // $1.50 // Division $halved = Money::USD(1000)->divide(2); echo $halved; // $5.00 // Modulo (remainder) $remainder = Money::USD(830)->mod(Money::USD(300)); echo $remainder; // $2.30 // Absolute value and negative $positive = Money::USD(-500)->absolute(); echo $positive; // $5.00 $negative = Money::USD(500)->negative(); echo $negative; // -$5.00 // Ratio calculation $ratio = Money::USD(500)->ratioOf(Money::USD(2)); echo $ratio; // 250 ``` ## Comparison Methods Compare Money objects using built-in comparison methods. All comparisons require the same currency. ```php use Cknow\Money\Money; $price = Money::USD(500); $otherPrice = Money::USD(500); $higherPrice = Money::USD(1000); $lowerPrice = Money::USD(100); // Equality check $isEqual = $price->equals($otherPrice); var_dump($isEqual); // bool(true) // Greater than comparisons var_dump($price->greaterThan($lowerPrice)); // bool(true) var_dump($price->greaterThanOrEqual($otherPrice)); // bool(true) // Less than comparisons var_dump($price->lessThan($higherPrice)); // bool(true) var_dump($price->lessThanOrEqual($otherPrice)); // bool(true) // State checks var_dump(Money::USD(0)->isZero()); // bool(true) var_dump(Money::USD(500)->isPositive()); // bool(true) var_dump(Money::USD(-500)->isNegative()); // bool(true) // Currency check var_dump(Money::USD(500)->isSameCurrency(Money::USD(100))); // bool(true) var_dump(Money::USD(500)->isSameCurrency(Money::EUR(100))); // bool(false) // Validate currency codes var_dump(Money::isValidCurrency('USD')); // bool(true) var_dump(Money::isValidCurrency('FAKE')); // bool(false) ``` ## Aggregation Functions Calculate minimum, maximum, average, and sum across multiple Money values. ```php use Cknow\Money\Money; $prices = [ Money::USD(100), Money::USD(200), Money::USD(300) ]; // Find minimum $min = Money::min($prices[0], $prices[1], $prices[2]); echo $min; // $1.00 // Find maximum $max = Money::max($prices[0], $prices[1], $prices[2]); echo $max; // $3.00 // Calculate average $avg = Money::avg($prices[0], $prices[1], $prices[2]); echo $avg; // $2.00 // Calculate sum $sum = Money::sum($prices[0], $prices[1], $prices[2]); echo $sum; // $6.00 // Using helper functions $minHelper = money_min(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')); $maxHelper = money_max(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')); $avgHelper = money_avg(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')); $sumHelper = money_sum(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')); ``` ## Formatting Methods Format Money objects for display using various formatting strategies including internationalized formats. ```php use Cknow\Money\Money; $price = Money::USD(500); // Default format (uses IntlMoneyFormatter) echo $price->format(); // $5.00 // Format as decimal number echo $price->formatByDecimal(); // 5.00 // Format with currency symbol (before/after) echo $price->formatByCurrencySymbol(); // $5.00 echo $price->formatByCurrencySymbol(true); // 5.00$ // Internationalized formatting echo $price->formatByIntl(); // $5.00 echo $price->formatByIntl('de_DE'); // 5,00 $ // Format as localized decimal echo $price->formatByIntlLocalizedDecimal(); // $5.00 // Format with specific number style echo Money::USD(199)->formatByIntl(null, null, \NumberFormatter::DECIMAL); // 1.99 // Bitcoin formatting echo Money::XBT(41000000)->formatByBitcoin(); // Ƀ0.41 // Custom formatter class PrefixFormatter implements \Money\MoneyFormatter { public function format(\Money\Money $money): string { return 'Price: ' . $money->getAmount() / 100; } } echo Money::USD(500)->formatByFormatter(new PrefixFormatter()); // Price: 5 ``` ## Parsing Methods Parse string representations of money into Money objects using multiple parsing strategies. ```php use Cknow\Money\Money; // Auto-detect currency from string $parsed = Money::parse('$1.00'); echo $parsed->getAmount(); // "100" echo $parsed->getCurrency()->getCode(); // "USD" // Parse with explicit currency $explicit = Money::parseByDecimal('1.00', 'USD'); echo $explicit; // $1.00 // Parse international formats $intl = Money::parseByIntl('$1.00'); echo $intl; // $1.00 $intlLocalized = Money::parseByIntlLocalizedDecimal('1.00', 'USD'); echo $intlLocalized; // $1.00 // Parse Bitcoin $bitcoin = Money::parseByBitcoin("\xC9\x830.41"); echo $bitcoin->getAmount(); // "41000000" // Using helper functions $helperParsed = money_parse('$5.00'); echo $helperParsed; // $5.00 $helperDecimal = money_parse_by_decimal('1.00', 'USD'); echo $helperDecimal; // $1.00 $helperIntl = money_parse_by_intl('$1.00'); echo $helperIntl; // $1.00 $helperBitcoin = money_parse_by_bitcoin("\xC9\x830.41"); echo $helperBitcoin->getAmount(); // "41000000" ``` ## Helper Functions Use global helper functions for quick Money and Currency operations without importing classes. ```php // Create currency instance $usdCurrency = currency('USD'); echo $usdCurrency->getCode(); // "USD" // Create money with default currency $defaultMoney = money(500); echo $defaultMoney; // $5.00 (uses config default) // Create money with specific currency $specificMoney = money(500, 'EUR'); echo $specificMoney; // €5.00 // Aggregation helpers $prices = [money(100, 'USD'), money(200, 'USD'), money(300, 'USD')]; echo money_min(...$prices); // $1.00 echo money_max(...$prices); // $3.00 echo money_avg(...$prices); // $2.00 echo money_sum(...$prices); // $6.00 // Parser helpers echo money_parse('$5.00'); // $5.00 echo money_parse_by_decimal('1.00', 'USD'); // $1.00 echo money_parse_by_intl('$1.00'); // $1.00 echo money_parse_by_intl_localized_decimal('1.00', 'USD'); // $1.00 ``` ## Eloquent Model Casts Cast database columns to Money objects automatically using Eloquent model casts. Choose from integer, decimal, or string storage formats. ```php use Cknow\Money\Casts\MoneyDecimalCast; use Cknow\Money\Casts\MoneyIntegerCast; use Cknow\Money\Casts\MoneyStringCast; use Cknow\Money\Money; class Product extends Model { protected $casts = [ // Store as decimal, use default currency from config 'price' => MoneyDecimalCast::class, // Store as integer (cents), specify currency 'cost' => MoneyIntegerCast::class . ':AUD', // Store as string, use currency from model's 'currency' attribute 'retail_price' => MoneyStringCast::class . ':currency', // Store as decimal with specific currency and force decimals 'wholesale' => MoneyDecimalCast::class . ':USD,true', ]; } // Usage $product = new Product(); // Set money values in various ways $product->price = 10; // $0.10 USD $product->price = 10.23; // $10.23 USD $product->price = 'A$10'; // $10.00 AUD $product->price = '1,000.23'; // $1,000.23 USD $product->price = Money::EUR(10); // €0.10 EUR // When using dynamic currency attribute $product->retail_price = '€13'; echo $product->currency; // 'EUR' (automatically set) echo $product->retail_price->getAmount(); // '1300' // Retrieve as Money object $price = $product->price; echo $price->format(); // $10.23 echo $price->add(Money::USD(100)); // $11.23 ``` ## Validation Rules Validate currency codes and money strings in Laravel form requests and validators. ```php use Cknow\Money\Rules\Currency; use Cknow\Money\Rules\Money as MoneyRule; use Illuminate\Support\Facades\Validator; // Currency validation $validator = Validator::make([ 'currency1' => 'USD', 'currency2' => 'EUR', 'currency3' => new \Money\Currency('BRL'), ], [ 'currency1' => new Currency(), 'currency2' => new Currency(), 'currency3' => 'currency', // string rule alias ]); var_dump($validator->passes()); // bool(true) // Money validation $validator = Validator::make([ 'money1' => '$10.00', 'money2' => '€10.00', 'money3' => 'R$10,00', ], [ // Basic money validation 'money1' => new MoneyRule(), // Force specific currency 'money2' => new MoneyRule('EUR'), // Force currency and locale 'money3' => new MoneyRule('BRL', 'pt_BR'), // Using string rule syntax 'money4' => 'money', 'money5' => 'money:EUR', 'money6' => 'money:BRL,pt_BR', ]); // In Form Request class StoreOrderRequest extends FormRequest { public function rules() { return [ 'amount' => ['required', new MoneyRule('USD')], 'currency' => ['required', new Currency()], ]; } } ``` ## Blade Directives Use Blade directives to display money and currency values in templates. ```php {{-- Display money with default currency --}} @money(500) {{-- Output: $5.00 --}} {{-- Display money with specific currency --}} @money(500, 'EUR') {{-- Output: €5.00 --}} {{-- Display currency --}} @currency('USD') {{-- Output: USD currency instance --}} {{-- Aggregation directives --}} @money_min(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')) {{-- Output: $1.00 --}} @money_max(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')) {{-- Output: $3.00 --}} @money_avg(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')) {{-- Output: $2.00 --}} @money_sum(money(100, 'USD'), money(200, 'USD'), money(300, 'USD')) {{-- Output: $6.00 --}} {{-- Parser directives --}} @money_parse('$5.00') {{-- Output: $5.00 --}} @money_parse_by_decimal('1.00', 'USD') {{-- Output: $1.00 --}} @money_parse_by_intl('$1.00') {{-- Output: $1.00 --}} @money_parse_by_intl_localized_decimal('1.00', 'USD') {{-- Output: $1.00 --}} ``` ## Serialization and JSON Convert Money objects to arrays and JSON for API responses and storage. ```php use Cknow\Money\Money; $price = Money::USD(500); // Convert to array (includes formatted value) $array = $price->toArray(); // Result: ['amount' => '500', 'currency' => 'USD', 'formatted' => '$5.00'] // Convert to JSON $json = $price->toJson(); // Result: {"amount":"500","currency":"USD","formatted":"$5.00"} // Direct JSON encoding (implements JsonSerializable) echo json_encode($price); // Output: {"amount":"500","currency":"USD","formatted":"$5.00"} // In API controller class ProductController extends Controller { public function show(Product $product) { return response()->json([ 'name' => $product->name, 'price' => $product->price->toArray(), // Full money data 'price_formatted' => $product->price->format(), // Just formatted string ]); } } // With custom attributes $money = Money::USD(500); $money->attributes(['tax_rate' => 0.08, 'discount' => 'SAVE10']); $serialized = $money->serialize(); // Result includes custom attributes merged with money data ``` ## Allocation Methods Distribute money across multiple recipients using ratios or equal parts with proper remainder handling. ```php use Cknow\Money\Money; // Allocate by ratios (e.g., splitting profits) $total = Money::USD(1000); // $10.00 $allocated = $total->allocate([50, 30, 20]); // 50%, 30%, 20% echo $allocated[0]; // $5.00 echo $allocated[1]; // $3.00 echo $allocated[2]; // $2.00 // Allocate equally to N recipients $splitEvenly = Money::USD(1000)->allocateTo(3); echo $splitEvenly[0]; // $3.34 echo $splitEvenly[1]; // $3.33 echo $splitEvenly[2]; // $3.33 // Note: $3.34 + $3.33 + $3.33 = $10.00 (remainder distributed) // Practical example: Splitting a bill $bill = Money::USD(10000); // $100.00 $shares = $bill->allocateTo(3); foreach ($shares as $index => $share) { echo "Person " . ($index + 1) . " pays: " . $share->format() . PHP_EOL; } // Person 1 pays: $33.34 // Person 2 pays: $33.33 // Person 3 pays: $33.33 ``` ## Summary Laravel Money is ideal for e-commerce applications, financial systems, accounting software, and any application requiring precise monetary calculations. Common use cases include product pricing, shopping cart totals, invoice generation, payment processing, multi-currency support, and financial reporting. The package integrates seamlessly with Laravel's validation, Eloquent ORM, and Blade templating systems. Integration follows standard Laravel conventions: install via Composer, publish configuration, add casts to models, and use helper functions or the Money class directly. The package handles currency conversion edge cases, rounding modes, and locale-specific formatting automatically. For complex scenarios, extend the base functionality with custom formatters, parsers, and serializers that implement the MoneyPHP interfaces.