Unused Closure Parameter
ID |
php.unused_closure_parameter |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
Php |
Tags |
code_smell, dead-code |
Description
Reports a closure parameter that is never referenced inside the closure body. The closure would behave identically without the parameter, so declaring one that is never read only misleads the reader into thinking the binding matters.
Rationale
A closure passed to array_map, usort, an event dispatcher or any higher-order function declares
exactly the parameters it intends to consume. A parameter that the body never reads is dead weight:
it suggests the closure depends on a value it ignores, and often hides a bug where the author meant
to use it. Removing the unused parameter (or, where the signature is dictated by the caller and a
trailing argument must be accepted, prefixing it with _) makes the closure’s real inputs obvious.
<?php
$totals = array_map(function ($row) { // OK — $row is used
return $row['amount'];
}, $rows);
$labels = array_map(function ($row, $index) {// FLAW — $index is never used
return $row['name'];
}, $rows);
$double = fn($n) => $n * 2; // OK — arrow parameter used
By-reference parameters (&$out) write back to the caller and are exempt. Underscore-prefixed
parameters ($_, $_unused) follow the explicit "intentionally ignored" convention and are exempt.
The variables captured by a use (…) clause are not parameters and are never reported. A closure
whose body reads variables dynamically (compact, extract, get_defined_vars, func_get_args)
is skipped.
Remediation
Remove the unused parameter. If the closure must keep the position to satisfy the caller’s signature
(for example a callback that always receives a key it does not need), rename it to _ or an
underscore-prefixed name to signal that the omission is deliberate.