Table of Contents
9. Readonly Classes — Declaring Immutable Objects With Intention
Readonly classes extend the idea of immutability from individual properties to the entire object.
They let us express that an object is a value
— something defined entirely by its construction and never changed afterward.
They reflect a broader shift in modern PHP:
→immutability should be intentional, visible, and effortless.
1. What Readonly Classes Are
A readonly class is declared with the readonly keyword:
readonly class Point { public function __construct( public float $x, public float $y, ) {} }
Every property is implicitly readonly.
Every property must be initialized in the constructor.
No property may change afterward.
The object becomes a stable value.
2. Why Modern PHP Uses Them
Readonly classes reduce:
- accidental mutation
- defensive copying
- boilerplate around value objects
- uncertainty about object state
They make value objects feel natural and honest.
3. The Mental Model
A readonly class is a value with a name.
It’s not an object that happens to be immutable.
It’s an object that declares immutability as part of its identity.
The key idea:
- Use readonly classes when the object represents a value,
not behavior.
4. A Simple Example
Without readonly classes:
class Point { public readonly float $x; public readonly float $y; public function __construct(float $x, float $y) { $this->x = $x; $this->y = $y; } }
With readonly classes:
readonly class Point { public function __construct( public float $x, public float $y, ) {} }
Same meaning.
Less ceremony.
More clarity.
5. When to Use Readonly Classes
Use them when:
- the object represents a value
- the state should never change
- the object is a DTO or domain primitive
- immutability improves reasoning
- we want to avoid defensive copying
Readonly classes shine in:
- coordinates
- money objects
- identifiers
- configuration values
- small domain concepts
6. When Not to Use Readonly Classes
Avoid them when:
- the object models behavior
- the state evolves over time
- the object interacts with external systems
- lazy initialization is required
- mutation is part of the domain *
Readonly classes are for values,
not actors.
When AI Gets This Wrong
AI often marks classes as readonly even when they represent evolving state. Sometimes it mixes readonly classes with setters, or tries to mutate properties after construction.
Our mental model helps us see when a class expresses a true value
— and when AI is using readonly simply because it “looks safe”.
Summary
Readonly classes let us declare immutable objects with clarity and intention.
They reduce noise, prevent accidental mutation,
and make value objects feel natural.
Once we internalize this,
we can immediately see when AI‑generated code:
- overuses readonly
- mixes readonly with mutable patterns
- applies readonly to behavioral objects
- or misses opportunities to express stable identity
Readonly classes are a small feature
— but they teach us
how modern PHP wants to express values with honesty and precision.
