Property Hooks (PHP 8.4)
debt(d7/e3/b3/t5)
Closest to 'only careful code review or runtime testing' (d7), since misuse of property hooks (complex logic, side effects) isn't reliably caught by phpstan and requires review.
Closest to 'simple parameterised fix' (e3), per quick_fix: replace getter/setter pairs with hooks, or move complex logic back into methods — localised per-property change.
Closest to 'localised tax' (b3), since hooks apply per-property within a class; they don't reshape system architecture but do create a stylistic commitment.
Closest to 'notable trap' (t5), per misconception: developers assume hooks replace all getters/setters and overuse them, plus virtual properties cannot be set directly — documented gotchas devs learn over time.
TL;DR
Explanation
Syntax: public string $name { get { return $this->name; } set(string $value) { $this->name = trim($value); } }. Shorthand set: set => trim($value). Virtual properties (no backing storage): public string $fullName { get => "$this->first $this->last"; }. A property with only get is implicitly read-only from outside. Abstract hooks in abstract classes and interfaces define contracts. Hooks interact with readonly: readonly properties can only have get hooks (PHP 8.4 allows set in clone). Backed vs virtual: backed has storage, virtual derives. Constructor promotion works with hooks.
Common Misconception
Why It Matters
Common Mistakes
- Putting complex business logic in hooks — keep hooks simple.
- Using hooks where readonly would suffice.
- Forgetting virtual properties cannot be set directly.
Code Examples
class User {
private string $_name;
public function getName(): string { return $this->_name; }
public function setName(string $v): void { $this->_name = trim($v); }
}
// PHP 8.4:
class User {
public string $name { set => trim($value); }
// Virtual — no backing storage:
public string $initials {
get => implode('', array_map(fn($w) => $w[0], explode(' ', $this->name)));
}
}