Table of Contents
8. Readonly Properties — Making Intentional Immutability Visible
Modern PHP gives us a simple, expressive way to declare that
a property will never change after construction.
readonly is not about restriction
— it’s about clarity.
It lets us express immutability as part of the object’s shape.
It reflects a broader shift in PHP 8.1+:
state should be explicit, stable, and intentional.
1. What readonly Is
A readonly property can be written once,
usually in the constructor,
and never changed again.
class User { public function __construct( public readonly string $id, public readonly string $email, ) {} }
After construction, these values are fixed.
They describe the identity of the object.
2. Why Modern PHP Uses It
Readonly properties give us:
- clear intent
- safer objects
- fewer accidental mutations
- easier reasoning
- better support for value‑like structures
They reduce the cognitive load of “can this change?”
—the answer becomes visible in the code.
3. The Mental Model
Readonly expresses stable identity.
It’s about making the shape of the object honest and predictable,
rather than locking things down.
The key idea?
- Use
readonlywhen a value is part of what the object is,
not what the object does.
4. A Simple Example
Without readonly:
class Point { public float $x; public float $y; }
These values could change at any time — even if they shouldn’t.
With readonly:
class Point { public function __construct( public readonly float $x, public readonly float $y, ) {} }
Now the intent is clear:
a Point is defined by its coordinates, not by behavior.
5. When to Use readonly
Use readonly when:
- the value is part of the object’s identity
- the property should never change after construction
- we're modeling value objects
- we want clarity and safety
- we want AI to stop mutating things that shouldn’t mutate
Readonly shines in DTOs, value objects, request models, and domain primitives.
6. When Not to Use readonly
Avoid readonly when:
- the property represents evolving state
- the object is meant to change over time
- the value depends on external conditions
- the property is lazily initialized
- the object models behavior, not identity
Readonly is for stable structure, not dynamic behavior.
When AI Gets This Wrong
AI often marks everything as readonly “just in case”, even when the object represents evolving state. Sometimes it mixes readonly with setters, or tries to mutate readonly properties later in the code.
Our mental model helps us see when readonly expresses true identity
—
and when AI is using it as decoration.
Summary
Readonly makes immutability visible.
It clarifies intent, reduces accidental mutation,
and helps the code reflect the object’s true shape.
Once we internalize this,
we can immediately see when AI‑generated code:
- overuses readonly
- mutates readonly properties
- mixes readonly with setters
- or misses opportunities to express stable identity
Readonly is a small feature
— but it teaches us how modern PHP wants to express meaning through structure.
