strange behaviour in foreach

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
periklis
Forum Newbie
Posts: 6
Joined: Fri May 30, 2008 6:19 am

strange behaviour in foreach

Post by periklis »

Could someone please explain me the following strange behaviour:

Code: Select all

 
<?php
echo "<pre>";
$arr = array(array(3 => 'foo'), false);
print_r($arr);
foreach ($arr as &$value) {}
print_r($arr);
foreach ($arr as $value) {}
print_r($arr);
echo "</pre>";
?>
 
Displays:

Code: Select all

 
Array
(
    [0] => Array
        (
            [3] => foo
        )
    [1] => 
)
Array
(
    [0] => Array
        (
            [3] => foo
        )
    [1] => 
)
Array
(
    [0] => Array
        (
            [3] => foo
        )
    [1] => Array
        (
            [3] => foo
        )
)
 
Thanks in advance!
dml
Forum Contributor
Posts: 133
Joined: Sat Jan 26, 2008 2:20 pm

Re: strange behaviour in foreach

Post by dml »

After running this:

Code: Select all

foreach ($arr as &$value) {}
Any assignment you make to $value will also assign to the last element in $arr, that is $arr[1].
Does that explain it sufficiently?
periklis
Forum Newbie
Posts: 6
Joined: Fri May 30, 2008 6:19 am

Re: strange behaviour in foreach

Post by periklis »

Well, it does explain it, but not sufficiently :)
I haven't made any assignments to the $arr after running the foreach code. I haven't done anything at all. Why does a simple loop over the array elements assign to the last value its previous one? Is this the normal behaviour?
dml
Forum Contributor
Posts: 133
Joined: Sat Jan 26, 2008 2:20 pm

Re: strange behaviour in foreach

Post by dml »

I'm trying to avoid long verbal explanations because I'll only make it sound more complicated than it is. Better to edge towards an understanding by playing with code examples. For a start, do you entirely understand what's going on below, and when you execute it, do you get the result you expected? It's nearly the same thing as your code example, but the foreach's have been temporarily removed:

Code: Select all

$arr = array(1, 2, 3);
$value =& $arr[2];
$value = 100;
print_r($arr);
periklis
Forum Newbie
Posts: 6
Joined: Fri May 30, 2008 6:19 am

Re: strange behaviour in foreach

Post by periklis »

Yeap, I understand this.
dml
Forum Contributor
Posts: 133
Joined: Sat Jan 26, 2008 2:20 pm

Re: strange behaviour in foreach

Post by dml »

Each iteration of a foreach loop involves the assignment of the loop variable followed by the execution of the loop body, which is empty in your example, so your foreach loops are actually just sequences of assignments. So below is your example with the loops decomposed into sequences of assignments. There's no extra tricks in this example than in the previous example, there are just a few more assignments to keep track of.

Code: Select all

 
$arr = array(array(3 => 'foo'), false);
print_r($arr);
 
// BREAK DOWN: foreach ($arr as &$value) {}
$value =& $arr[0];
$value =& $arr[1];
print_r($arr);
 
// BREAK DOWN foreach ($arr as $value) {}
$value = $arr[0];
$value = $arr[1];
print_r($arr);
 
periklis
Forum Newbie
Posts: 6
Joined: Fri May 30, 2008 6:19 am

Re: strange behaviour in foreach

Post by periklis »

Now I think I'm starting to get it. So, when the first loop finishes, $value points to the same place as $arr[1].
When the second loop starts, $value becomes $arr[0], but since $value is a reference to $arr[1], $arr[1] also becomes $arr[0].
Thus in the end, you get the last value being the same as the first previous one

Thank your really very much, this explanation really helped me!
Post Reply