Skip to main content
The AsIntegerMoney cast stores monetary values in their minor units (e.g., cents for USD, pence for GBP). This is the recommended approach for handling money in databases as it avoids floating-point precision issues.
Why integers? Storing $10.00 as 1000 cents instead of 10.00 ensures exact arithmetic. This is the standard practice in financial applications.

How It Works

The cast automatically converts between Money objects in your PHP code and integer values in your database:
  • Storage: Money::of(10.00, 'USD')1000 (stored as integer)
  • Retrieval: 1000Money::ofMinor(1000, 'USD') (Money object)

Implementation

The AsIntegerMoney class uses the AsMoneyCast trait and implements two key methods:
AsIntegerMoney.php
protected function serializeMoney(Money $value): string
{
    return (string) $value->getMinorAmount();
}

protected function deserializeMoney(float|int|string $amount, string $currency): Money
{
    return Money::ofMinor($amount, $currency);
}

Usage Patterns

Store amount and currency in separate columns for better queryability.

Model Definition

use Devhammed\LaravelBrickMoney\Money;
use Devhammed\LaravelBrickMoney\Casts\AsIntegerMoney;
use Illuminate\Database\Eloquent\Model;

/**
 * @property Money $amount
 * @property string $currency
 */
class Transaction extends Model
{
    protected function casts(): array
    {
        return [
            'amount' => AsIntegerMoney::of('currency'),
        ];
    }
}

Migration

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::create('transactions', function (Blueprint $table) {
    $table->id();
    $table->bigInteger('amount');      // e.g., 1000 = $10.00
    $table->string('currency', 3);     // e.g., 'USD'
    $table->timestamps();
});

Usage Example

// Create
$transaction = Transaction::create([
    'amount' => Money::of(10.00, 'USD'),
]);

// The database stores:
// amount: 1000
// currency: "USD"

// Retrieve
$transaction = Transaction::find(1);
echo $transaction->amount->format();  // "$10.00"
echo $transaction->currency;          // "USD"
The currency column is automatically populated when you set the amount.

Cryptocurrency Support

Some cryptocurrencies have very high precision (e.g., Ethereum uses 18 decimal places). For these cases, the stored integer can exceed the BIGINT limit.
For high-precision cryptocurrencies, use string columns instead of bigInteger to avoid overflow:
Schema::create('crypto_transactions', function (Blueprint $table) {
    $table->id();
    $table->string('amount');        // Can store very large numbers
    $table->string('currency', 10);
    $table->timestamps();
});

Example with Ethereum

use Devhammed\LaravelBrickMoney\Money;

// 1 ETH = 1,000,000,000,000,000,000 wei (18 decimals)
$transaction = CryptoTransaction::create([
    'amount' => Money::of(1, 'ETH'),
]);

// Database stores: "1000000000000000000"

Complete Example

Here’s a full example showing common operations:
use Devhammed\LaravelBrickMoney\Money;
use Devhammed\LaravelBrickMoney\Casts\AsIntegerMoney;
use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    protected function casts(): array
    {
        return [
            'subtotal' => AsIntegerMoney::of('currency'),
            'tax' => AsIntegerMoney::of('currency'),
            'total' => AsIntegerMoney::of('currency'),
        ];
    }

    public function calculateTotal(): void
    {
        $this->total = $this->subtotal->plus($this->tax);
    }
}

Querying

Since amounts are stored as integers, you can query them directly:
// Find orders over $100 (10000 cents)
$expensiveOrders = Order::where('total', '>', 10000)->get();

// Find orders between $50 and $200
$midRangeOrders = Order::whereBetween('total', [5000, 20000])->get();

// Sum all orders in USD
$totalRevenue = Order::where('currency', 'USD')->sum('total');
echo Money::ofMinor($totalRevenue, 'USD')->format();
Remember to convert your query amounts to minor units when comparing!

Best Practices

1

Always use separate columns for queryability

Separate columns allow you to filter, sort, and aggregate by amount or currency.
'amount' => AsIntegerMoney::of('currency')  // ✅ Recommended
'amount' => AsIntegerMoney::class           // ⚠️ Less flexible
2

Use string columns for high-precision currencies

Cryptocurrencies and some exotic currencies may need larger storage.
$table->string('amount');  // For crypto
$table->bigInteger('amount');  // For standard currencies
3

Add database indexes for frequently queried columns

$table->bigInteger('amount')->index();
$table->string('currency', 3)->index();
4

Document property types in PHPDoc

/**
 * @property Money $amount
 * @property string $currency
 */
class Transaction extends Model { }

Advantages

Precision

No floating-point errors - perfect for financial calculations

Storage Efficiency

Integers are more compact than decimals

Query Performance

Integer comparisons are faster than decimal

Industry Standard

Used by Stripe, PayPal, and major payment processors

Next Steps

AsDecimalMoney Cast

Learn about decimal-based storage

AsCurrency Cast

Cast currency codes to objects

Build docs developers (and LLMs) love