Constructor Property Promotion (PHP 8.0)
debt(d3/e1/b1/t3)
Closest to 'default linter catches the common case' (d3). The term's detection_hints list rector, phpcs, and php-cs-fixer as tools that can detect the old declare-parameter-assign pattern and suggest promotion. These are standard PHP ecosystem tools that most projects already use, making detection automated and routine.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix explicitly states: 'Add public/protected/private visibility to constructor parameters to promote them to properties automatically.' This is literally adding one keyword per parameter — a trivial mechanical transformation that rector can automate.
Closest to 'minimal commitment' (b1). Constructor promotion is pure syntax sugar that affects only the class where it's used. It doesn't impose any ongoing maintenance tax, doesn't affect architecture, and can be adopted or reversed on a per-class basis without affecting the rest of the codebase.
Closest to 'minor surprise' (t3). The misconception field notes that developers may think promotion is 'just syntactic sugar with no semantic difference,' but promoted properties are actually declared as class properties participating in serialization and reflection. This is a documented gotcha but not severe — once learned, it's straightforward. The common_mistakes confirm this is about edge cases (mixing styles, serialization awareness) rather than catastrophic misunderstanding.
Also Known As
TL;DR
Explanation
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.
Common Misconception
Why It Matters
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.
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.
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.
Code Examples
// PHP 7-style verbosity that promotion eliminates:
class Point {
public float $x;
public float $y;
public function __construct(float $x, float $y) {
$this->x = $x; // All redundant with PHP 8 promotion
$this->y = $y;
}
}
// PHP 8.0 constructor promotion — eliminates boilerplate
// Before:
class Product {
public int $id;
public string $name;
public float $price;
public function __construct(int $id, string $name, float $price) {
$this->id = $id;
$this->name = $name;
$this->price = $price;
}
}
// After — declare, assign, and type in one place:
class Product {
public function __construct(
public readonly int $id,
public readonly string $name,
public readonly float $price,
) {}
}