PHP is a loosely typed language. Most of the time this is very useful because you as a programmer don't have to worry about typecasting: it's done for you. However, on some occasions this can cause some unexpected trouble. These issues can be hard to track down because the error usually doesn't show up at the place where you define your variable, but at the place where you want to use them (which can be in a totally different part of your application).
In this blog I want to point out what can happen if you try to access object properties by reference when the object is not initialized. Although this is not caused by typecasting, the encountered problems can be pretty similar on some occasions.
Take a look at the amazing application I just built:
PHP:
<?php
class myApp
{
protected $myVar;
public function runMe()
{
$this->printMyVar();
$a = &$this->myVar->nonExistingArray['a'];
$this->printMyVar();
print_r($this->myVar);
}
protected function printMyVar()
{
echo ('The class of myVar is:' . get_class($this->myVar) . "\n");
}
}
$myApp = new myApp();
$myApp->runMe();
?>
Well nothing special really. The printMyVar method tries to display the classname of the myVar member variable. Of course, this won't work as the myVar variable isn't initialized anywhere, so in that case get_class will simply return ''. Then we suddenly start using the variable as an object - basically we try to get a value out of a non-existing array from our non-existing object, by reference (this is probably the code of some really messed up programmer; don't try this at home). What would you expect to happen? You probably expect nothing really. $a would probably stay empty, or some error would occur for using an undefined variable as an object.
Wrong! Instead, trying to access a property in a non-initialized variable by-reference seems to cast the non-initialized variable ($myVar) into an object of the class stdClass! That's right, the output of the script above is:
CODE:
The class of myVar is:stdClass
stdClass Object
(
[nonExistingArray] => Array
(
[a] =>
)
)
We even created our array with the arraykey 'a' and no value! Amazing, isn't it? Please note that this only happens when you try to get the value by-reference. This of course allows us to fill our array by setting $a, and by that I can imagine this feature can be very powerful as long as you actually intended to use it that way. In fact PHP is saying "Okay so you want access to an undefined array key in an undefined array in an non-existing object? No problem let me create them for you.". On the other hand, in some occasions (especially larger applications than the example above) this can cause some trouble. When you forget to create an object and you try to access it this way you are suddenly talking to an stdClass-object instead of the fooBar-class you actually intended to use. You might not even see an error at that point, but the application could act weird or cause an error in a totally different part of your application (for example when you try to call a method on the object).
So how to prevent this? First of all, don't forget to create your object

. Besides that people should be careful with using '&' for accessing object properties by-reference. On some occasions this can be useful, but most of the time you can get away with the 'normal' way of getting and setting those values:
CODE:
$a = $this->myVar->nonExistingArray['a'];
Getting the value by-value instead of by-reference won't create an object. Don't worry about memory usage, because PHP uses lazy copy which means the value won't be copied until you actually change its value - so if you just want to know the value and not change it this works fine. And of course when we want to change the value we can use:
CODE:
$this->myVar->nonExistingArray['a'] = 2;
This will simply cause an error when myVar isn't an object, so is a lot safer to use as well.
So to sum things up:
- When you want to create an object, don't forget to create it
- Be careful with getting values by-reference and only use it when you really have to