PHP has some idiosyncrasies that can cause odd or counter intuitive behavior. This will be a series of short posts covering some of these situations.

Let’s have a look at the following simple piece of code:

$arr = array('foo','bar','baz');


foreach($arr as &$item){
   echo "First array: ".$item."\n";
}
foreach($arr as $item){
   echo "Second array: ".$item."\n";
}

What would the output of this be? Surprisingly this does the following:

First array: foo
First array: bar
First array: baz
Second array: foo
Second array: bar
Second array: bar

So what’s going on here? Notice that the first line loops over each item as &$item. The & operator in PHP uses a reference to the original item rather than a copy.

For example:

$a = 'Foo';
$b = $a;
$c = &$a;

$a = 'Bar';
echo $a."\n";
echo $b."\n";
echo $c."\n";

This will output:

Bar
Foo
Bar

$b was pointing to a copy so the value is unchanged. $c however was pointing directly to $a so it’s value has changed to match $a.

So back to our original example. The first loop loops as usual but leaves the $item variable in scope. This is now pointing at the last element of $arr.

Crucially because we used &$item when defining it if we change the value of $item we change the last element in the array!

Our second loop now comes along and each time it loops $item is set to a new value which changes the value in the array. Finally when we get to the last element it has been set to bar which is what is displayed.

In some situations using & can be very useful however care should be taken as it can cause some odd issues like the above.