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.