{
    "slug": "constructor_promotion",
    "term": "Constructor Property Promotion (PHP 8.0)",
    "category": "php",
    "difficulty": "beginner",
    "short": "Declare and assign class properties directly in constructor parameters using visibility modifiers, eliminating boilerplate.",
    "long": "Constructor property promotion (PHP 8.0) combines property declaration, constructor parameter declaration, and property assignment into a single concise syntax. Adding a visibility modifier (public, protected, private) or readonly before a constructor parameter automatically creates the property and assigns the argument to it. For example, public function __construct(private string $name, private readonly int $age) {} replaces six lines of boilerplate. Works with readonly (PHP 8.1) for immutable value objects.",
    "aliases": [
        "PHP 8 constructor promotion",
        "promoted properties",
        "property promotion"
    ],
    "tags": [
        "php8",
        "php",
        "oop",
        "syntax"
    ],
    "misconception": "Constructor promotion is just syntactic sugar with no semantic difference. Promoted properties are also automatically declared as class properties — omitting the explicit property declaration is not optional boilerplate, it is the actual declaration.",
    "why_it_matters": "Constructor property promotion (PHP 8.0+) eliminates the repetitive declare-parameter-assign pattern, reducing boilerplate by 60-70% for value objects and DTOs while remaining fully equivalent.",
    "common_mistakes": [
        "Mixing promoted and non-promoted properties in a way that makes the class harder to understand.",
        "Using promotion with complex constructor logic — promotion is best for simple assignment; add validation in the body.",
        "Not realising that promoted properties are declared on the class, not just in the constructor — they participate in serialization and reflection.",
        "Using promotion in abstract constructors — can confuse subclass implementations."
    ],
    "when_to_use": [
        "Simple DTOs and value objects where every parameter maps directly to a stored property.",
        "Immutable objects — combine promoted properties with readonly for concise immutable classes.",
        "Eliminating boilerplate in classes with 3+ constructor parameters that are plain assignments.",
        "New PHP 8.0+ code where the constructor has no logic beyond storing values."
    ],
    "avoid_when": [
        "The constructor contains validation or transformation logic that must run before the property is assigned.",
        "The property needs to be private but the constructor parameter is public-facing.",
        "You need to assign a value that depends on another parameter or runtime state.",
        "The class is abstract and subclasses need to override constructor behaviour."
    ],
    "related": [
        "readonly_properties",
        "named_arguments",
        "value_object"
    ],
    "prerequisites": [
        "type_declarations",
        "readonly_properties",
        "named_arguments"
    ],
    "refs": [
        "https://www.php.net/manual/en/language.oop5.decon.php#language.oop5.decon.constructor.promotion"
    ],
    "bad_code": "// PHP 7-style verbosity that promotion eliminates:\nclass Point {\n    public float $x;\n    public float $y;\n    public function __construct(float $x, float $y) {\n        $this->x = $x; // All redundant with PHP 8 promotion\n        $this->y = $y;\n    }\n}",
    "good_code": "// PHP 8.0 constructor promotion — eliminates boilerplate\n\n// Before:\nclass Product {\n    public int    $id;\n    public string $name;\n    public float  $price;\n\n    public function __construct(int $id, string $name, float $price) {\n        $this->id    = $id;\n        $this->name  = $name;\n        $this->price = $price;\n    }\n}\n\n// After — declare, assign, and type in one place:\nclass Product {\n    public function __construct(\n        public readonly int    $id,\n        public readonly string $name,\n        public readonly float  $price,\n    ) {}\n}",
    "quick_fix": "Add public/protected/private visibility to constructor parameters to promote them to properties automatically — eliminates boilerplate assignment",
    "severity": "low",
    "effort": "low",
    "created": "2026-03-15",
    "updated": "2026-03-25",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/constructor_promotion",
        "html_url": "https://codeclaritylab.com/glossary/constructor_promotion",
        "json_url": "https://codeclaritylab.com/glossary/constructor_promotion.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": "[Constructor Property Promotion (PHP 8.0)](https://codeclaritylab.com/glossary/constructor_promotion) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/constructor_promotion"
            }
        }
    }
}