← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Property Hooks (PHP 8.4)

php PHP 8.0+ Advanced
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7), PHPStan may catch some hook misuse but infinite recursion or silently-discarded set values typically surface only at runtime or in review.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3), fixing a hook recursion or missing assignment is localized to the property declaration, slightly more than a one-liner because the hook pattern must be corrected.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3), property hooks are scoped to individual classes/properties; the choice doesn't propagate system-wide though it does shape class API conventions.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7), the misconception that hooks replace all getters/setters plus the infinite-recursion gotcha (accessing $this->property inside its own hook) contradicts how getters work in other languages.

About DEBT scoring →

Also Known As

property hooks PHP 8.4 hooks get hook set hook PHP84

TL;DR

PHP 8.4 property hooks attach get and set logic directly to a property declaration — co-locating validation and transformation with the property itself.

Explanation

PHP 8.4 property hooks: get hook runs when the property is read; set hook runs when written. Short form: public string $name { set => ucfirst($value); } applies a transformation on every assignment. Long form with full validation: public int $age { set { if ($value < 0) throw new ValueError(); $this->age = $value; } }. Hooks can be abstract in interfaces. Work with constructor promotion. $value in set holds the incoming value. Hooks do not replace complex computed properties — use methods for those.

Common Misconception

Property hooks replace all getter/setter methods — hooks are best for simple validation and transformation at the property level; complex computed properties or significant side effects are still clearer as explicit methods.

Why It Matters

PHP 8.4 property hooks eliminate the common boilerplate of private property + getter + setter validation, keeping the logic co-located with the property declaration and reducing class noise.

Common Mistakes

  • Infinite recursion in a get hook that reads the same property — access $this->fieldName not $this->property
  • Set hook that forgets to assign $this->property = $value — the incoming value is silently discarded
  • Complex business logic in hooks — extract to methods for clarity
  • Hooks on static properties — not supported in PHP 8.4

Code Examples

✗ Vulnerable
// PHP 8.3 boilerplate — three members for one concept:
class User {
    private string $_email;
    public function getEmail(): string { return $this->_email; }
    public function setEmail(string $email): void {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) throw new ValueError();
        $this->_email = strtolower($email);
    }
}
✓ Fixed
// PHP 8.4 property hooks — co-located logic:
class User {
    public string $email {
        set {
            if (!filter_var($value, FILTER_VALIDATE_EMAIL))
                throw new ValueError('Invalid email: ' . $value);
            $this->email = strtolower($value); // Assign to $this->email
        }
    }
    // Short hook for simple transformation:
    public string $name { set => ucwords(strtolower($value)); }
}

$user = new User();
$user->email = 'ALICE@EXAMPLE.COM'; // Validated + lowercased automatically
$user->name  = 'john doe';           // Becomes 'John Doe' automatically

Tags


Added 16 Mar 2026
Edited 22 Mar 2026
Views 21
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 7 Google 3 Perplexity 2 Unknown AI 2 ChatGPT 2 Ahrefs 1
crawler 15 crawler_json 2
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Medium
⚡ Quick Fix
Use PHP 8.1 Fibers or PHP's built-in observer hooks (register_tick_function, pcntl_signal) for process-level lifecycle hooks — framework-level: use Symfony events or Laravel lifecycle hooks
📦 Applies To
PHP 8.0+ web cli queue-worker laravel symfony
🔗 Prerequisites
🔍 Detection Hints
No lifecycle hooks for long-running PHP processes; missing SIGTERM handler in queue workers; no shutdown function registered for cleanup
Auto-detectable: ✗ No phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant