Spread Operator & Variadic Args (PHP 5.6)
debt(d5/e3/b3/t3)
Closest to 'specialist tool catches it' (d5), because detection_hints lists rector and phpcs with code_pattern matching func_get_args() and call_user_func_array() — these are specialist static analysis / code-style tools, not default linters or compiler errors. The pattern is detectable automatically but requires these tools to be configured.
Closest to 'simple parameterised fix' (e3), because quick_fix describes replacing func_get_args() with ...$params and call_user_func_array($fn, $args) with $fn(...$args) — a small, mechanical pattern replacement within one component. It's more than a single-line patch because multiple call sites may need updating, but it doesn't span the whole codebase architecturally.
Closest to 'localised tax' (b3), because the applies_to scope is broad (web, cli, queue-worker) but the common_mistakes are localised to function signatures and call sites. The burden is a persistent but contained tax — if old patterns like func_get_args() or call_user_func_array() are used, each affected function pays the cost but the rest of the codebase is largely unaffected.
Closest to 'minor surprise' (t3), because the misconception states that developers think ...args is only for variadic function definitions, missing that spread (...) also works in function calls to unpack any iterable. This is a one-directional edge-case misunderstanding, not a catastrophic or deeply contradictory trap — just a partial mental model that omits the call-site unpacking usage.
TL;DR
Explanation
PHP 5.6: variadic params: function sum(int ...$nums) { return array_sum($nums); }. Spread in calls: sum(...[1,2,3]). Before PHP 5.6: func_get_args() and call_user_func_array(). PHP 7.4 extended spread to arrays: [...$a, ...$b]. PHP 8.1 extended to string-keyed arrays. Variadic params must be last in parameter list. Type-hinting variadics: function join(string ...$parts). Named arguments (PHP 8.0) interact with variadics. The spread operator in function calls unpacks arrays/iterables into positional arguments.
Common Misconception
Why It Matters
Common Mistakes
- Putting variadic param before other params — must be last.
- Not type-hinting variadic params.
- Still using call_user_func_array instead of fn(...$args).
Code Examples
// PHP 5.5 and older:
function sum() {
return array_sum(func_get_args());
}
call_user_func_array('sum', $numbers);
// PHP 5.6+:
function sum(int ...$nums): int {
return array_sum($nums);
}
sum(1, 2, 3);
sum(...[1, 2, 3]); // Spread from array
// Forwarding all args:
function wrapper(...$args) {
return original(...$args);
}