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.

  1. rxq reblogged this from techpriester
  2. techpriester posted this