Back to All Nuggets
PHP php ⏱️ 2 min read
Production Implementation
Ask endoAI
<?php

declare(strict_types=1);

namespace App\Domain\ValueObjects;

use InvalidArgumentException;

readonly class Money
{
    public function __construct(
        public int $amountInCents,
        public string $currency = 'KES'
    ) {
        if ($this->amountInCents < 0) {
            throw new InvalidArgumentException("Amount cannot be negative.");
        }
    }

    public static function fromDecimal(float $amount, string $currency = 'KES'): self {
        return new self((int)round($amount * 100), $currency);
    }

    public function toDecimal(): float {
        return $this->amountInCents / 100;
    }
}

Enforcing True Domain Safety with Native Readonly Classes in PHP 8.2+

PHP 8.2 introduced native readonly class declarations, ensuring that every property cannot be modified after constructor initialization.

  • Domain Validation: A Money object cannot exist in an invalid state.
  • Thread-Safe: Immutable objects can be passed across jobs and events without unexpected side-effects.

Accelerate Your Engineering Career

Get monthly masterclasses, exclusive code snippets, and direct architectural reviews.

Become a Supporter • KES 500 / Month