[Solution] PHP each() Deprecated — Replace with foreach() Migration

The each() function was deprecated in PHP 7.2 and removed in PHP 8.0. It was commonly used in older PHP code to iterate over arrays by returning the current key-value pair and advancing the internal pointer. Modern PHP code should use foreach loops, which are cleaner, faster, and more readable.

What You’ll See

On PHP 7.2 through 7.4:

Deprecated: each() is deprecated in /path/to/script.php on line X

On PHP 8.0+:

Fatal error: Uncaught Error: Call to undefined function each()

Why Deprecated

each() had several drawbacks:

  • Readability: It obscures the intent of the loop compared to foreach.
  • Internal pointer: It relies on the array’s internal pointer, which can lead to subtle bugs if the pointer is moved unexpectedly.
  • Performance: foreach is optimized internally in the PHP engine and runs faster.
  • Limited functionality: each() cannot iterate over objects or generators, while foreach can.

Old Code (Deprecated)

// Basic each() iteration
$colors = ["red", "green", "blue"];
while (list($key, $value) = each($colors)) {
    echo "$key => $value\n";
}

// each() with a for-style loop
$names = ["Alice" => 30, "Bob" => 25, "Charlie" => 35];
reset($names);
while (list($name, $age) = each($names)) {
    echo "$name is $age years old\n";
}

// Using each() to get the current element without a loop
$fruits = ["apple", "banana", "cherry"];
$current = each($fruits);
print_r($current);
// Output: Array ( [1] => apple [value] => apple [0] => 0 [key] => 0 )

New Code (Replacement)

// Basic foreach iteration — clean and direct
$colors = ["red", "green", "blue"];
foreach ($colors as $key => $value) {
    echo "$key => $value\n";
}

// foreach with associative arrays
$names = ["Alice" => 30, "Bob" => 25, "Charlie" => 35];
foreach ($names as $name => $age) {
    echo "$name is $age years old\n";
}

// When you only need the current element (replacing each() for single-use)
$fruits = ["apple", "banana", "cherry"];
$first_key = array_key_first($fruits);  // PHP 7.3+
$first_value = $fruits[$first_key];
echo "First: $first_key => $first_value\n";

// Get both key and value of the current element without a loop
$key = key($fruits);
$value = current($fruits);
echo "Current: $key => $value\n";

// Iterating with both key and value in foreach
$scores = ["math" => 95, "science" => 88, "english" => 92];
foreach ($scores as $subject => $score) {
    $grade = $score >= 90 ? "A" : ($score >= 80 ? "B" : "C");
    echo "$subject: $score ($grade)\n";
}

Key Differences

PatternOld (each())New (foreach)
Key-value iterationwhile (list($k, $v) = each($arr))foreach ($arr as $k => $v)
Value onlywhile (list(, $v) = each($arr))foreach ($arr as $v)
Reset pointer firstreset($arr) requiredNot needed
Modifying valueseach() does not allow itforeach ($arr as &$v) with reference

The foreach loop handles the internal pointer automatically, so you never need to call reset() before iterating.

Migration Steps

  1. Find all each() calls in your codebase:
grep -rn "\beach\s*(" --include="*.php" /path/to/project/
  1. Replace while + list() + each() patterns with foreach. The conversion is almost always a direct translation:
// Before
reset($arr);
while (list($k, $v) = each($arr)) { ... }

// After
foreach ($arr as $k => $v) { ... }
  1. Replace standalone each() calls (used to get one element) with key() and current(), or use array_key_first() on PHP 7.3+.

  2. If modifying values, use the reference syntax foreach ($arr as &$value) and unset the reference afterward to avoid accidental modifications.

  3. Run your test suite. The foreach loop resets the pointer internally, so any code that depends on the pointer position after the loop may behave differently.