Arrow Functions (PHP 7.4)
debt(d3/e1/b1/t5)
Closest to 'default linter catches the common case' (d3). Tools like rector, php-cs-fixer, and phpstan (all listed in detection_hints.tools) can automatically detect verbose closures that could be replaced with arrow functions, and flag misuse patterns like multi-line logic attempts. Rector can even auto-refactor closures to arrow functions. This is slightly above d3 since these are standard PHP toolchain tools, not specialist SAST tools.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix directly describes a single-line replacement: converting function($x) use ($var) { return $x * $var; } to fn($x) => $x * $var. Misuses like using arrow functions where closures are needed (multi-line, by-reference capture) are similarly one-line swaps back to a regular closure.
Closest to 'minimal commitment' (b1). Arrow functions are a local syntactic convenience for callbacks and short closures. They don't impose architectural constraints, don't affect system shape, and each usage is independently swappable with a regular closure. No ongoing maintenance tax on the codebase.
Closest to 'notable trap' (t5). The misconception field highlights a significant gotcha: developers assume arrow functions and closures are identical, but arrow functions capture by value only — mutations don't propagate outward. This contradicts JavaScript arrow function behavior where outer variables can be modified freely. The common_mistakes list reinforces this: expecting to modify outer variables, trying multi-line logic, and nesting deeply are all documented pitfalls that competent developers will encounter.
Also Known As
TL;DR
Explanation
Arrow functions (fn($x) => $x * 2) are a shorthand for closures that evaluate a single expression and implicitly capture outer-scope variables by value — no use clause needed. They are particularly useful with array functions like array_map() and array_filter(). Arrow functions cannot capture by reference, cannot span multiple statements, and cannot use yield. They return the value of the expression automatically.
Common Misconception
Why It Matters
Common Mistakes
- Using arrow functions for multi-line logic — they only support a single expression, use regular closures for complex bodies.
- Expecting to modify outer variables — arrow functions capture by value, mutations do not propagate outward.
- Using them for class methods — arrow functions are for callbacks and closures, not method definitions.
- Nesting arrow functions three or four levels deep — readability collapses fast, extract named functions instead.
Code Examples
// Verbose closure when arrow function suffices:
$multiplier = 3;
$result = array_map(function($n) use ($multiplier) {
return $n * $multiplier;
}, $numbers);
// Better: $result = array_map(fn($n) => $n * $multiplier, $numbers);
// Arrow functions (PHP 7.4) — implicit capture, single expression
$multiplier = 10;
// Traditional closure — requires explicit 'use'
$fn1 = function(int $n) use ($multiplier): int { return $n * $multiplier; };
// Arrow function — captures $multiplier automatically
$fn2 = fn(int $n): int => $n * $multiplier;
// Great for array operations
$prices = array_map(fn(Product $p) => $p->price * 1.2, $products);
$active = array_filter($users, fn(User $u) => $u->isActive() && !$u->isBanned());
// Chained transformations
$result = array_map(
fn($item) => $item->total * (1 - $item->discountRate),
array_filter($items, fn($item) => $item->status === 'paid')
);