← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Constructor Promotion + readonly Together

php PHP 8.1+ Intermediate
debt(d1/e1/b2/t5)
d1 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'caught instantly' (d1), attempting to modify a readonly property outside the constructor produces an immediate Error at runtime, and phpstan/rector (per detection_hints) flag misuse statically.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch' (e1), per quick_fix: simply combine `public readonly Type` in constructor parameters — a single signature change per property.

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

Closest to 'minimal commitment' (b1), slightly higher because choosing readonly value objects propagates immutability expectations to callers (no setters, must clone-with), but applies_to is localised to the DTO/value-object classes themselves.

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

Closest to 'notable trap' (t5), grounded in misconception: developers expect clone to allow modification of readonly props, but pre-8.3 it cannot, and post-8.3 only inside __clone() — a documented gotcha most devs eventually learn.

About DEBT scoring →

TL;DR

PHP 8.1+ allows readonly in constructor promotion: public function __construct(public readonly string $name) — the cleanest way to write immutable value objects.

Explanation

Constructor promotion (PHP 8.0) and readonly (PHP 8.1) combine elegantly. public readonly string $name in the constructor parameter list declares, promotes, and marks the property immutable in one line. PHP 8.2 adds readonly classes — mark the entire class and all promoted properties become readonly without individual annotation. Readonly properties can only be initialised once (in the constructor) and cannot be modified thereafter — attempting to set them throws an Error. Cloning: PHP 8.3 allows readonly property modification in __clone().

Common Misconception

Readonly properties can be modified by clone — before PHP 8.3 they cannot. Post-8.3, only in __clone() is modification allowed.

Why It Matters

Combined constructor promotion + readonly eliminates 4-5 lines of boilerplate per property, making value objects and DTOs dramatically more concise.

Common Mistakes

  • Trying to set a readonly property outside the constructor.
  • Not using readonly classes (PHP 8.2) when all properties should be immutable.
  • Confusing readonly (write-once) with const (compile-time constant).

Code Examples

✗ Vulnerable
class Money {
    public readonly int $amount;
    public readonly string $currency;

    public function __construct(int $amount, string $currency) {
        $this->amount = $amount;
        $this->currency = $currency;
    }
}
✓ Fixed
// PHP 8.1+ — combined promotion + readonly:
class Money {
    public function __construct(
        public readonly int $amount,
        public readonly string $currency,
    ) {}
}

// PHP 8.2 — readonly class:
readonly class Money {
    public function __construct(
        public int $amount,
        public string $currency,
    ) {}
}

Added 22 Mar 2026
Views 23
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 1 ping S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 4 Unknown AI 3 Google 2 ChatGPT 1 Meta AI 1 Ahrefs 1
crawler 17 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🔵 Info ⚙ Fix effort: Low
⚡ Quick Fix
Combine public readonly Type in constructor parameters. Use readonly class (PHP 8.2) when all properties should be immutable.
📦 Applies To
PHP 8.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
public readonly|readonly class
Auto-detectable: ✓ Yes rector phpstan
🤖 AI Agent
Confidence: Low False Positives: Medium ✓ Auto-fixable Fix: Low Context: Class

✓ schema.org compliant