PHP Behavior Pointers and Arrays

I was reading the PHP manual (in particular each()

) and came across the following warning:

Note
Since assigning an array to another variable resets the original pointer to the array, our example above would result in an infinite loop if we were to assign $ fruit to another variable inside the loop.

And an example:

<?php
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

reset($fruit);
while (list($key, $val) = each($fruit)) {
    echo "$key => $val\n";
}
?>

      

Good. It makes sense. But I decided to make a simple test:

<?php
    $fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

    foreach ($fruit as $key => $name) {
        printf("[%s] => [%s]\n", $key, $name);
    }

    $fruit2 = $fruit;
    echo current($fruit);
?>

      

Expected result: pointer reset. My question is, is the pointer reset only after the end of the array?

For example:

<?php
    $fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

    foreach ($fruit as $key => $name) {
        printf("[%s] => [%s]\n", $key, $name);
    }

    reset($fruit);
    next($fruit)."\n";
    $fruit2 = $fruit;
    echo current($fruit);
?>

      

The pointer remains in the second element of the array ('b' => 'banana')

. Is this behavior specific to the language?

Thanks and sorry for the bad english.

+3


source to share


2 answers


Is this behavior specific to the language?

The "pointer" value in PHP arrays is not the same as the generic "pointer" value (in C / C ++ or other languages, which gives the programmer direct memory access).

There are no pointers in PHP. The array data type stores inside the cursor within the list of values ​​it contains. It is called the internal array pointer, and modified functions reset()

, next()

, prev()

, end()

, each()

and possibly others. It can be used to iterate over an array like this:

$array = array(1, 2, 3);
while (list($key, $val) = each($array)) {
    echo($key.' => '.$val."\n");
}

      

There is no reliable way to iterate through an array using next()

or prev()

as they return FALSE

when there are no more elements to iterate over, but they also return FALSE

when the value is FALSE

stored as an element in the array.

They can be useful if you only need to parse a few elements from the beginning (or end) of an array. FE let's say we have an array of integers returned by a function and we need to get the first value that is not zero.

But this task can be accomplished even easier using foreach()

:

$array = array(0, 0, 0, 2, 0, 1, 0, 3);
foreach ($array as $val) {
    if ($val != 0) {
        break;
    }
}
echo($val);           // prints "2"

      

or array_shift()

:

$array = array(0, 0, 0, 2, 0, 1, 0, 3);
do {
    $val = array_shift($array);
    if ($val != 0) {
        break;
    }
} while(count($array));
echo($val);           // prints "2"

      



Expected result: pointer reset. My question is, is the pointer reset only after the end of the array?

The documentation foreach()

is wrong. It might have been correct in PHP 3 and PHP 4, but I think the behavior has changed (better) since the introduction of iterators in PHP 5 foreach()

.

It says:

The first time you run foreach, the internal array pointer is automatically reset to the first element of the array. This means you don't need to call reset () before your foreach loop.

Because foreach relies on an internal array pointer, changing it in a loop can lead to unexpected behavior.

A simple test contradicts this statement:

$array = array(1, 3, 5, 7, 9);

foreach ($array as $val1) {
    foreach ($array as $val2) {
        echo('$val1='.$val1.'; $val2='.$val2.'; ');
    }
    echo("\n");
}

      

This works without issue. It shouldn't work if foreach()

using an internal array pointer. This probably creates a copy of the pointer.

You can also try using the current()

, next()

, prev()

or reset()

inside foreach()

, and you'll get an amazing and sometimes inconsistent results.

Better to use it foreach()

to iterate over arrays and not rely on an internal pointer.

Functions reset()

and end()

, however, are very handy when you need to get the first and last elements of an array without worrying about keys.

+4


source


Yes, the pointer will only be reset after the end of the array. Since foreach takes a pointer to the end of the array, it will automatically be reset after $ fruit2 = $ fruit; and will also reset if you go manually at the end of the array using next () as below code



<?php
$fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

foreach ($fruit as $key => $name) {
    printf("[%s] => [%s]\n", $key, $name);
}

reset($fruit);
next($fruit)."\n";
next($fruit)."\n";
next($fruit)."\n";
$fruit2 = $fruit;
echo current($fruit);
?>

      

+2


source







All Articles