array_map / filter / reduce as FP Patterns
debt(d7/e3/b3/t5)
Closest to 'only careful code review or runtime testing' (d7). The key misuse — forgetting array_values() after array_filter() — produces no error or warning at runtime in most paths; it silently preserves non-sequential keys and only manifests as a bug when JSON encoding converts the array to an object instead of an array, or when downstream code assumes 0-indexed keys. The detection_hints list only Rector, which handles refactoring patterns rather than detecting this specific key-preservation gotcha automatically.
Closest to 'simple parameterised fix' (e3). The quick_fix notes adding array_values(array_filter($arr)) when sequential keys are needed — a small, localised change. It may need to be applied across multiple call sites if the pattern is repeated, but each fix is a simple wrapper addition rather than a structural refactor.
Closest to 'localised tax' (b3). The choice to use array_map/filter/reduce is localised to the specific transformation logic. It applies broadly across web/cli/queue contexts (per applies_to), but each usage is independent; there is no strong gravitational pull on the rest of the codebase. Nested usage or large-dataset concerns are contained to the affected code paths.
Closest to 'notable trap' (t5). The misconception is clearly documented: array_filter() preserves original keys, not re-indexing to 0-based. This contradicts many developers' intuition that filtering produces a clean sequential array, and it causes subtle JSON encoding bugs (object vs. array). It is a widely-known gotcha that most PHP developers encounter, placing it squarely at t5.
TL;DR
Explanation
Functional array operations: array_map(fn, array) — transforms each element, returns new array. array_filter(array, fn) — removes elements where fn returns false, preserves keys. array_reduce(array, fn, initial) — folds array to single value. Combining: array_values(array_filter(array_map(fn, $data))). PHP 8.1 arrow functions (fn($x) => $x*2) make these concise. Caveats: array_filter() preserves keys — use array_values() to re-index. array_map() with multiple arrays fills shorter ones with null. For large datasets, generators are more memory-efficient than array_map.
Common Misconception
Why It Matters
Common Mistakes
- Forgetting array_filter preserves keys — causes issues with JSON encoding expecting arrays.
- Using array_map when a generator would use less memory for large datasets.
- Nested array_map/filter — consider a single loop for readability beyond 2 levels.
Code Examples
$result = [];
foreach ($users as $user) {
if ($user->isActive()) {
$result[] = $user->getName();
}
}
$result = array_map(
fn(User $u) => $u->getName(),
array_filter($users, fn(User $u) => $u->isActive())
);
// Sum with reduce:
$total = array_reduce($orders, fn($carry, $o) => $carry + $o->amount, 0);