A PHP WTF: foreach scoping

Round and round we goI just discovered a little PHP gotcha when using elements by reference in a foreach each that I thought I’d share. Apparently, if do a foreach loop by reference, then loop over the same array again later in the same script, you cannot re-use the same element variable name otherwise strange and scary things will happen.
Check out the following code:

<!--?php 
$a = new stdClass();
$a--->Id = 1;
 
$b = new stdClass();
$b-&gt;Id = 2;
 
$c = new stdClass();
$c-&gt;Id = 3;
 
$objects = array($a, $b, $c);
 
print "This first pass is fine:\n";
foreach ($objects as &amp;$object)
{
    print 'Id: ' . $object-&gt;Id . "\n";
}
 
print "\n";
 
print "This second pass will be weird:\n";
foreach ($objects as $object)
{
    print 'Id: ' . $object-&gt;Id . "\n";
}
 
print "\n";
 
print "This third pass will be equally weird:\n";
foreach ($objects as $object)
{
    print 'Id: ' . $object-&gt;Id . "\n";
}
 
print "\n";
 
print "WTF?!\n";
?&gt;

Produces the following output:

This first pass is fine:
Id: 1
Id: 2
Id: 3

This second pass will be weird:
Id: 1
Id: 2
Id: 2

This third pass will be equally weird:
Id: 1
Id: 2
Id: 2

WTF?!

Notice the output of the 2nd and 3rd loop iterations? There’s no element “3”. WTF? This was biting me in the ass this evening and eventually I broke down and read theĀ PHP foreach documentation. There I noticed a nice little cavaet:

Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

<sarcasm>Well that’s just awesome</sarcasm> Anyway, I hope this saves you some heartache. I guess I’m just too used to Perl ;-D

Leave a Reply

Your email address will not be published. Required fields are marked *