{
    "slug": "php8_readonly_classes",
    "term": "readonly Classes (PHP 8.2)",
    "category": "php",
    "difficulty": "beginner",
    "short": "PHP 8.2 readonly classes make all promoted properties readonly automatically — the cleanest way to define immutable value objects and DTOs.",
    "long": "readonly class Money { } makes all declared properties implicitly readonly — no need to mark each one. Rules: all properties must be typed. Cannot have untyped or static properties. Allows constructor promotion. Can extend readonly classes. Cannot extend non-readonly classes (or vice versa — asymmetric readonly inheritance breaks the contract). readonly classes implement all readonly property restrictions: write-once, no unset, requires type. PHP 8.3: readonly properties can be modified in __clone() for copy-with patterns. Ideal for: DTOs, value objects, request/response objects, command/query objects.",
    "aliases": [],
    "tags": [
        "php",
        "php82",
        "readonly",
        "immutability",
        "dto",
        "history"
    ],
    "misconception": "readonly classes prevent all mutation — readonly prevents property writes, but objects inside properties can still be mutated (shallow immutability). Use clone + new values for copy-with.",
    "why_it_matters": "readonly classes eliminate property-by-property readonly annotation while enforcing immutability for entire value object families — cleaner and safer.",
    "common_mistakes": [
        "Trying to extend a non-readonly class from readonly class — fatal error.",
        "Adding static properties to readonly class — not allowed.",
        "Assuming deep immutability — nested objects are still mutable."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "php8_readonly_intro",
        "php_readonly_promotion",
        "value_object",
        "php_object_cloning_security"
    ],
    "prerequisites": [
        "php8_readonly_intro"
    ],
    "refs": [
        "https://www.php.net/manual/en/migration82.new-features.php"
    ],
    "bad_code": "class UserDTO {\n    public function __construct(\n        public readonly int $id,\n        public readonly string $name,\n        public readonly string $email,\n    ) {}\n}",
    "good_code": "// PHP 8.2 — readonly class:\nreadonly class UserDTO {\n    public function __construct(\n        public int $id,\n        public string $name,\n        public string $email,\n    ) {}\n\n    // PHP 8.3 copy-with:\n    public function withName(string $name): static {\n        $clone = clone $this;\n        $clone->name = $name; // Only in __clone in 8.3\n        return $clone;\n    }\n}",
    "quick_fix": "Convert value objects and DTOs to readonly classes. Remove individual readonly keywords — the class declaration covers all properties.",
    "severity": "info",
    "effort": "low",
    "created": "2026-03-23",
    "updated": "2026-03-23",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/php8_readonly_classes",
        "html_url": "https://codeclaritylab.com/glossary/php8_readonly_classes",
        "json_url": "https://codeclaritylab.com/glossary/php8_readonly_classes.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[readonly Classes (PHP 8.2)](https://codeclaritylab.com/glossary/php8_readonly_classes) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/php8_readonly_classes"
            }
        }
    }
}