Readonly Properties and Classes
PHP 8.1 added readonly properties — set once, then immutable. PHP 8.2 extended this to entire classes. Immutability is no longer a convention; it's enforced by the engine.
// Readonly properties (PHP 8.1)
class Invoice {
public function __construct(
public readonly string $number,
public readonly float $total,
public readonly DateTimeImmutable $issuedAt,
) {}
}
$invoice = new Invoice('INV-001', 250.00, new DateTimeImmutable());
$invoice->total = 0; // Error: Cannot modify readonly property Invoice::$total
// Readonly classes (PHP 8.2) — all properties are implicitly readonly
readonly class Money {
public function __construct(
public int $amount,
public string $currency,
) {}
public function add(Money $other): self {
if ($this->currency !== $other->currency) {
throw new \InvalidArgumentException('Currency mismatch');
}
return new self($this->amount + $other->amount, $this->currency);
}
}
$price = new Money(1000, 'EUR');
$tax = new Money(210, 'EUR');
$total = $price->add($tax); // New object — originals unchanged
Readonly properties make value objects trivial to implement correctly. No more writing private properties with getters, no more worrying about someone mutating shared state. The language guarantees immutability.
Significance: Correctness
Immutability eliminates entire categories of bugs: unexpected mutation, shared state corruption, order-dependent initialization. When the engine enforces that a value can't change, you can reason about your code with confidence.