DisconnectedForeachInstruction
info off by defaultGroup: Control flow · PhpStorm name: DisconnectedForeachInstructionInspection
A statement inside a foreach body that uses no loop variable and nothing the loop body changes produces the same effect on every iteration; it most likely belongs before or after the loop. Optionally (off by default) the rule also points at objects instantiated on every iteration that could be built once and cloned.
Example
php
<?php
/* @var array $orders */
$type = \ArrayObject::class;
foreach ($orders as $key => $order) {
$box = new $type();
$node = (new \DOMDocument())->createElement('row');
syslog(LOG_INFO, $banner);
while ($pending > 0) {
usleep($pending);
}
if ($debugMode) {
dump($settings);
}
switch ($mode) {
default:
}
try {
$warmup();
} catch (\RuntimeException $problem) {
report($problem);
}
echo '<br>'; // E4: no variables
if ($stop) { return; } // E3
$total += $order; // E2 + connected
$copy = clone $template; // clone: never reported
$sink[] = 'seen'; // accumulate
$logger->push($order); // D8a: $logger becomes modified
$logger->flush(); // connected through $logger
preg_match('/x/', $order, $hits); // D8b: $hits modified
print_r($hits); // connected
$meta->touch(compact('key')); // D11: depends on $key
}
foreach ($groups as $group) {
foreach ($group as $member) {
echo $group; // D4: outer loop variable
}
}
foreach ($rows as $row) {
?><td><?= $title ?></td><?php // E5: inline HTML, loop skipped
}Reported:
- line 5: Create the object once before the loop and clone it here.
- line 6: Create the object once before the loop and clone it here.
- line 8: Statement does not depend on the loop; move it out.
- line 9: Statement does not depend on the loop; move it out.
- line 12: Statement does not depend on the loop; move it out.
- line 15: Statement does not depend on the loop; move it out.
- line 18: Statement does not depend on the loop; move it out.
Options
| Option | Type | Default | Effect |
|---|---|---|---|
| SUGGEST_USING_CLONE | bool | false | Enables D13 (object creation on every iteration). The upstream test suite runs with it enabled. |
Configure
In custos.json:
json
{
"rules": {
"DisconnectedForeachInstruction": {
"enabled": true,
"options": {
"SUGGEST_USING_CLONE": false
}
}
}
}Suppress
Before the statement or declaration (or the first statement of the file), either of:
php
// @custos-ignore DisconnectedForeachInstruction
/**
* @noinspection DisconnectedForeachInstructionInspection
*/