← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Readonly Classes (PHP 8.2)

PHP PHP 8.2+ Advanced
debt(d3/e1/b3/t5)
d3 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'default linter catches the common case' (d3); Rector and PHPStan (listed in detection_hints.tools) can flag classes where all properties are individually readonly and suggest the class-level keyword, and inheritance violations are fatal errors caught instantly by PHP itself.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch' (e1); per quick_fix, the change is adding the `readonly` keyword to the class declaration and removing it from each property — a trivial single-line modification per class.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3); applies to individual value object / DTO classes, doesn't ripple across the system, though it does constrain inheritance hierarchies for those classes.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5); per misconception, the inheritance rules (readonly class can only extend readonly or property-less abstract classes) are a documented gotcha, plus the confusion with PHP 8.1 readonly properties and the typed-property requirement listed in common_mistakes.

About DEBT scoring →

Also Known As

PHP 8.2 readonly classes readonly class inheritance

TL;DR

Marking an entire class readonly makes all its properties implicitly readonly — ideal for immutable value objects and DTOs with minimal boilerplate.

Explanation

PHP 8.2 introduced readonly classes: declaring readonly class Point {} makes every declared property automatically readonly and typed — no need to mark each individually. All properties must be typed; dynamic properties are forbidden. Readonly classes cannot be extended by non-readonly classes and cannot declare static properties. They are perfect for value objects, DTOs, and command/query objects where immutability should be a class-level guarantee. Combined with constructor promotion, they enable very concise immutable data structures with no setter methods to maintain.

Common Misconception

Readonly classes can freely extend non-readonly classes. A readonly class can only extend another readonly class or an abstract class with no declared properties — extending a class with non-readonly properties is a fatal error.

Why It Matters

PHP 8.2 extended readonly to the class level, eliminating the boilerplate of marking every property readonly individually — a readonly class communicates immutability intent at a glance.

Common Mistakes

  • Confusing readonly classes (PHP 8.2, all properties readonly) with readonly properties (PHP 8.1, per-property).
  • Attempting to declare non-typed properties in a readonly class — all properties must be typed.
  • Using readonly classes for entities that need lazy loading or mutation after construction.
  • Not realising that readonly classes can still have non-readonly static properties.

Code Examples

✗ Vulnerable
// PHP 8.1 — manual readonly on each property:
class Point {
    public function __construct(
        public readonly float $x,
        public readonly float $y,
        public readonly float $z,
    ) {}
}

// PHP 8.2 — class-level readonly:
readonly class Point {
    public function __construct(
        public float $x,
        public float $y,
        public float $z,
    ) {}
}
✓ Fixed
readonly class Coordinate {
  public function __construct(
    public float $lat,
    public float $lng,
  ) {}
}

Added 15 Mar 2026
Edited 13 Jun 2026
Views 119
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 1 ping M 1 ping T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 1 ping M
Amazonbot 1
SEMrush 1
Ahrefs 23 Amazonbot 11 PetalBot 10 Scrapy 7 Perplexity 6 Google 5 SEMrush 5 Twitter/X 3 Unknown AI 2 Applebot 2 Meta AI 1 Brave Search 1 Bing 1
crawler 75 crawler_json 2
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
PHP php A server-side scripting language that generates web pages and APIs — the code runs on the server, and only its output (usually HTML or JSON) reaches the browser.

PHP is often the first server-side language people meet, and understanding its execution model — script starts fresh on every request, no memory between requests — explains most of how the web backend works: sessions, databases, and caching all exist to bridge that per-request amnesia.

💡 Start with PHP 8.x, declare(strict_types=1), and PDO — skip any tutorial that mentions mysql_query().

Ask Codex about PHP →
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
Upgrade PHP 8.1 classes with all-readonly properties to PHP 8.2 readonly class — one keyword covers all properties; use for DTOs, value objects, and command/query objects
📦 Applies To
PHP 8.2+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
PHP 8.2+ class with each property individually marked readonly when readonly class would cover all; value object without readonly class
Auto-detectable: ✓ Yes rector phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✓ Auto-fixable Fix: Low Context: Class

✓ schema.org compliant