← Home ← Codex ← DEBT ← Engine
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 114
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping W 0 pings T 0 pings F 1 ping S 2 pings S 0 pings M 0 pings T 1 ping W 0 pings T 2 pings F 2 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 10 Ahrefs 7 SEMrush 7 ChatGPT 6 Google 6 Bing 6 Scrapy 6 PetalBot 6 Unknown AI 5 Perplexity 4 Meta AI 2 Twitter/X 2 Applebot 2 Brave Search 2 Claude 1
crawler 66 crawler_json 4 your_contextpost 1 pre-tracking 1
🧱 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
🔵 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