Skip to content

ForeachInvariants ​

warning on by default quick-fix

Group: Control flow · PhpStorm name: ForeachInvariantsInspection

Two loop shapes that are really array iterations in disguise:

  1. a counter-based for that walks 0 … count($a) and reads $a[$i];
  2. a while (list($k, $v) = each($a)) loop (each() is slow, deprecated in PHP 7.2 and removed in PHP 8). Both are clearer (and faster) as foreach.

Example ​

php
<?php
function render(array $rows, $cap) {
    $total = count($rows);
    for ($n = 0; $n < $total; $n++) {
        print $rows[$n];
        echo $rows[$n]->title, " ({$rows[$n]}) ";
        $label = strtoupper($rows[$n]);
        $alias = &$rows[$n];
        if ($rows[$n] instanceof Stringable) {}
    }
    for ($n = 0; count($rows) > $n; ++$n) {
        $rows[$n][1] = 'x';
        echo $rows[$n][2];
    }
    while (list($slot, $entry) = each($rows)) {
        echo $entry;
    }
    for ($n = 0; $n < $cap; $n++) { echo $rows[$n]; }               // E5: parameter
    for ($n = 1; $n < count($rows); $n++) { echo $rows[$n]; }       // E2
    while (list($slot, $entry) = each($rows)) { unset($rows[$slot]); } // E7
}
php
<?php
function render(array $rows, $cap) {
    foreach ($rows as $n => $nValue) {
        print $rows[$n];
        echo $nValue->title, " ($nValue) ";
        $label = strtoupper($nValue);
        $alias = &$rows[$n];
        if ($nValue instanceof Stringable) {}
    }
    foreach ($rows as $n => $nValue) {
        $rows[$n][1] = 'x';
        echo $nValue[2];
    }
    foreach ($rows as $entry) {
        echo $entry;
    }
    for ($n = 0; $n < $cap; $n++) { echo $rows[$n]; }               // E5: parameter
    for ($n = 1; $n < count($rows); $n++) { echo $rows[$n]; }       // E2
    while (list($slot, $entry) = each($rows)) { unset($rows[$slot]); } // E7
}

Reported:

  • line 4: Iterate with foreach instead of a counter loop.
  • line 11: Iterate with foreach instead of a counter loop.
  • line 15: Replace the each() loop with foreach.

Configure ​

In custos.json:

json
{
  "rules": {
    "ForeachInvariants": {
      "enabled": false
    }
  }
}

Suppress ​

Before the statement or declaration (or the first statement of the file), either of:

php
// @custos-ignore ForeachInvariants

/**
 * @noinspection ForeachInvariantsInspection
 */

Released under the MIT License. Rule catalogue modelled on Php Inspections (EA Extended); independent clean-room implementation.