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.