The PHP language has a couple of quirky behaviours which can catch you out unexpectedly if you don't know what to look for. Here are two I've discovered recently:
1. all variables that contain instantiated objects are references to that object, and explicit "references" actually refer to ... er, the variable (symbol) table, or something ..?
The only way I can explain is by means of example:
<?php class SimpleClass { function __construct() { $this->var = ''; } } $instance = new SimpleClass(); // $assigned = $instance; // copy assignment $reference =& $instance; // reference assignment $instance->var = 'asdasd'; // change the field in the original instance $reference = null; // make the 'reference' variable point to nothing var_dump($reference); // => NULL, as expected var_dump($assigned); // => object(SimpleClass)#1 (1) { ["var"] => string(6) "asdasd" } var_dump($instance); // => NULL
Two things to take away:
$assigned = $instance
creates a second variable which refers to the original object; and$reference =& $instance
essentially means that $reference
is now an alias for $instance
, and anything you do to one also happens to the other. I don't know any other language that has these sorts of references.If you change $reference = null
to $instance = null
the final output is the same. $reference
and $instance
are the same variable (albeit spelled differently.)
2. foreach
maintains a reference to an array, even if you overwrite the array variable inside the loop.
<?php $foo = array(1,2,3); foreach ($foo as $x) { echo $x; $foo = array(4,5,6); } var_dump($foo);
...which outputs:
1 2 3 array(3) { [0] => int(4) [1] => int(5) [2] => int(6) }
While you're inside the loop, the iterator always refers to the object originally identified by the variable.
For a more potentially destructive example, we can overwrite $foo
with something that can't be foreach
ed over:
<?php $foo = array(1,2,3); foreach ($foo as $x) { echo $x; $foo = $x; } var_dump($foo);
...which outputs:
1 2 3 int(3)
And now for something that will hopefully make you cringe:
<?php $foo = array(1,2,3); foreach ($foo as $foo) { echo $foo; } var_dump($foo);
Yes, apparently this is valid, even though we're overwriting the array with its own members in a horribly obfuscating and mind-hurting way. The output is:
1 2 3 int(3)
...which I suppose makes sense, once you realise that the foreach
loop seems to have created a safe reference to the original $foo
array. Note that the second $foo
variable doesn't mask or shadow the outer-scope's foo, it overwrites it, just as if you did the assignment inside the loop body.