compact() & extract() — Variable Packing
debt(d5/e3/b3/t7)
Closest to 'specialist tool catches it' (d5). PHPStan and Psalm can detect some compact() issues, but as noted in detection_hints, 'PHPStan cannot detect variable existence after extract()' — the silent omission of undefined variables in compact() is similarly hard to catch statically since the tool must track variable scope and string-name matching. Standard linters flag usage but not the subtle bugs.
Closest to 'simple parameterised fix' (e3). The quick_fix indicates replacing compact() with explicit array literals — this is straightforward within a single file/function, but requires identifying all variable names that should be in the array and writing them out explicitly. Not a one-liner, but contained to the call site.
Closest to 'localised tax' (b3). While compact() applies across all PHP contexts (web/cli/queue), its damage is localised to individual call sites. It doesn't create architectural coupling — each usage can be fixed independently. The burden is mostly that refactoring tools can't rename variables referenced as strings, affecting only that specific code path.
Closest to 'serious trap' (t7). The misconception field explicitly states the trap: compact() 'silently ignores undefined variables in PHP 7 (only a notice)' — this contradicts reasonable expectations that building an array from named variables would error on missing variables. A developer from other languages would expect a runtime error, not silent omission. The string-based coupling also breaks IDE refactoring in ways developers don't anticipate.
Also Known As
TL;DR
Explanation
compact('name', 'email') returns ['name' => $name, 'email' => $email] — handy for passing local variables to templates. extract($array) imports array keys as variables into the current scope. The critical danger: extract($_POST) injects arbitrary variable names, potentially overwriting $isAdmin, $authenticated, or any other security variable. This is the root of the register_globals disaster. Never call extract() on user-supplied data. compact() with undefined variable names triggers a notice in PHP 7.3+ and an error in 8.0+. Prefer explicit assignments for clarity and safety.
Common Misconception
Why It Matters
Common Mistakes
- Renaming a variable without updating the compact() call — the key silently disappears from the result.
- Using compact() for view data instead of explicit array literals — harder to read and trace.
- Not realising compact() silently ignores undefined variables in PHP 7.3+, returning NULL in older versions.
- Using compact() with user-controlled variable names — potential information disclosure if the variable exists.
Code Examples
extract($_POST); // injects arbitrary variables — $isAdmin could be overwritten
$name = htmlspecialchars($_POST['name'] ?? '');
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);