PHP associativity and assign by reference

Today a rare thing happened. I found a new practical issue in PHP that you might have to watch out for if you are porting some legacy code to be more 5.3 happy. I was happily removing assign by reference when all of a sudden a fatal error happened. The culprit was a simple line while ($p = $ps->get() && ++$i<50).

Now, if you know your operator precedence you will realize that unless this loop ran enough times, $p = true, but it was supposed to be an object! What really happened is best shown by running this gist.


<?php
$objects = array(new stdClass, new stdClass);
while ($o =& next($objects) && true)
    var_dump($o); // stdClass object 
reset($objects);
while ($o = next($objects) && true)
    var_dump($o); // true
// Fix
reset($objects);
while (($o = next($objects)) && true)
    var_dump($o); // stdClass object

The issue is that the reference operator takes precedence over the && operator, thus by removing the reference operator the precedence rules makes $p into the result of the combined expression. This is an easy mistake to make, and it can potentially be harder to spot. Had i not used the object explicitly in the same loop it would have been more convoluted.

Its easy to get around by taking charge over precedence with parentheses as in the third loop in the gist. In general you should keep your tongue straight when doing assignment and comparison in the same expression.