Protect your late statics!
In PHP 5.3 we got a great feature called “late static binding”. If you don’t know it yet, read about it here.
However, there’s a little problem that may confuse some people and that may also lead to quite unexpected behaviour, if you don’t pay attention to it. Let me demonstrate:
<?php
class Foo
{
static public $foo = 23;
}
class Bar extends Foo
{
public function __construct()
{
static::$foo = 42;
}
}
echo 'Foo: '.Foo::$foo.PHP_EOL; // 23
echo 'Bar: '.Bar::$foo.PHP_EOL; // 23
$o1 = new Bar();
echo 'Bar: '.Bar::$foo.PHP_EOL; // 42
Bar::$foo = 5;
echo 'Foo: '.Foo::$foo.PHP_EOL; // 5 ... ouch!
As expected, The call to Bar::__construct() accesses the static member $foo in the context of Bar and not Foo. If I had used “self::” instead of “static::”, it’d have changed the value of Foo::$foo. So that’s all working fine.
The problem occurs when I change the value of Bar::$foo from the outside, which is allowed because I declared it as public. Now, since there is no late static binding for the Paamayim Nekudotayim (Yes, that’s the correct name for “::”) outside of the class it is operating on, I actually changed Foo::$foo intead of Bar::$foo. This may be bad.
To avoid this issue, just declare our static members private and unless you want this to happen, access them via public getter/setter methods that can make use of the late static binding.