{
    "slug": "readonly_classes",
    "term": "Readonly Classes (PHP 8.2)",
    "category": "php",
    "difficulty": "intermediate",
    "short": "Marking an entire class readonly automatically makes all its declared properties readonly, simplifying immutable value object creation.",
    "long": "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.",
    "aliases": [
        "PHP 8.2 readonly class",
        "readonly class"
    ],
    "tags": [
        "php8",
        "php",
        "oop",
        "immutability"
    ],
    "misconception": "A readonly class is just a class where all properties happen to be readonly. Declaring a class readonly implicitly marks all properties readonly and prevents adding dynamic properties — it also clearly signals intent, helping static analysers enforce immutability contracts.",
    "why_it_matters": "PHP 8.2 readonly classes make all properties readonly by default — ideal for value objects and DTOs where immutability should be enforced without marking each property individually.",
    "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."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "readonly_properties",
        "value_object",
        "immutability",
        "constructor_promotion"
    ],
    "prerequisites": [
        "readonly_properties",
        "constructor_promotion",
        "immutability"
    ],
    "refs": [
        "https://www.php.net/manual/en/language.oop5.properties.php#language.oop5.properties.readonly-properties"
    ],
    "bad_code": "class Point { public function __construct(\n  public readonly float $x,\n  public readonly float $y,\n) {} }",
    "good_code": "readonly class Point { public function __construct(\n  public float $x,\n  public float $y,\n) {} } // readonly on class covers all properties",
    "quick_fix": "Add readonly before class to make all promoted and explicit properties readonly at once — perfect for DTOs, value objects, and query result types",
    "severity": "low",
    "effort": "low",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/readonly_classes",
        "html_url": "https://codeclaritylab.com/glossary/readonly_classes",
        "json_url": "https://codeclaritylab.com/glossary/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/readonly_classes) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/readonly_classes"
            }
        }
    }
}