Readonly Classes (PHP 8.2)
debt(d3/e1/b3/t5)
Closest to 'default linter catches the common case' (d3), Rector and PHPStan (from detection_hints.tools) can flag classes where all properties are individually readonly and suggest the class-level readonly modifier; parse errors on PHP <8.2 are caught instantly but the missed-opportunity case needs a tool.
Closest to 'one-line patch' (e1), quick_fix is literally adding the readonly keyword before class — a single-token change consolidating per-property readonly declarations.
Closest to 'localised tax' (b3), applies_to scopes this to DTOs/value objects within a codebase; immutability commitment is real but contained to those classes, and consumers of value objects rarely feel the weight beyond constructing new instances instead of mutating.
Closest to 'notable trap' (t5), the misconception undersells real gotchas documented in common_mistakes — static properties are not covered, clone cannot modify properties, and inheritance rules (readonly class cannot extend non-readonly and vice versa) surprise developers who assume 'all properties readonly' is the whole story.
Also Known As
TL;DR
Explanation
PHP 8.2 extended the readonly keyword from individual properties to entire class declarations. A readonly class implicitly makes all typed, non-static properties readonly — they can only be initialised in the constructor. This is ideal for DTOs, value objects, and command/query objects. Untyped properties are not allowed in readonly classes. Cloning a readonly object with modified properties requires clone with property initialisation syntax (PHP 8.3+ adds clone with syntax). Combining with constructor property promotion gives maximally concise immutable objects.
Common Misconception
Why It Matters
Common Mistakes
- Trying to use readonly classes with properties that need to change after construction — they are for immutable objects.
- Not knowing that readonly classes were added in PHP 8.2 — using the syntax on 8.1 causes a parse error.
- Adding mutable static properties to readonly classes — static properties are not affected by readonly.
- Cloning readonly class instances hoping to modify properties — clone creates an identical immutable copy.
Code Examples
class Point { public function __construct(
public readonly float $x,
public readonly float $y,
) {} }
readonly class Point { public function __construct(
public float $x,
public float $y,
) {} } // readonly on class covers all properties