Search code examples
php-5.5php-7.1

Why does array traversal differ between php5 and php7


Consider some array:

$data = [
    "k0"=>"v0",
    "k1"=>"v1",
    "k2"=>"v2",
    "k3"=>"v3",
    "k4"=>"v4",
];

Traverse over array $data and print array $result_1

$result_1 = [];
while (key($data)) {
    $result_1[key($data)] = current($data);
    next($data);
}
print_r($result_1);

//Then perform the same operation in a function supplying the same array $data as argument 
//(mind that the internal pointer of $data is at the end):

traverse($data);

function traverse($arr){
    $result_2 = [];
    while (key($arr)) {
        $result_2[key($arr)] = current($arr);
        next($arr);
    }
    print_r($result_2);
}

If running the above code on php-5.5 $result_1 and $result_2 are the same:

//Array ( [k0] => v0 [k1] => v1 [k2] => v2 [k3] => v3 [k4] => v4 ) 

If running on php-7.1 $result_1 is the same as above but $result_2 is empty:

//Array ( )

Why does array traversal differ between php-5.5 and php-7.1?


Solution

  • I've filed a bug in PHP :: Bug #77014. The correct/intended behaviour is the one present in PHP 7+. I'm quoting the answer from [email protected]:

    The behavior is intended. Passing an array to a function does not change the position of the internal array pointer. I believe the PHP 5 behavior was some kind of artifact of key() accepting the array by reference and triggering a separation there.

    If you'd like to make sure that you are iterating the array from the start rather than from the previous position of the internal array pointer, you can perform an explicit call to reset().

    (I'd recommend moving away from these functions entirely, if it is at all possible. If complex iteration patterns are involved, ArrayIterator may be an alternative.)

    Mystery solved I guess.