3
class A
{
    static $v = "A";

    static function echoExtendedStaticVariable() {
        echo self::$v;
    }
}

class B extends A
{
    static $v = "B";
    // override A's variable with "B"
}

Why does:

echo B::$v

print "A"?

And how do I get it to print "B"?

Is there a way to do this before PHP 5.3?

Alex V
  • 18,176
  • 5
  • 36
  • 35

2 Answers2

6

B->echoExtendedStaticVariable() == 'A' because self:: is evaluated at compile-time, not run-time. It's as if you wrote A:: instead of self::.

What you want is a feature called "late static binding"--it's "late" because it can determine the class at runtime instead of at compile-time.

You can emulate this (sort-of) in PHP 5.2 using ReflectionClass:

class A
{
    static $v = "A";
    function echoExtendedStaticVariable() {
        $rc = new ReflectionClass($this);
        echo $rc->getStaticPropertyValue('v');
    }
}
class B extends A
{
    static $v = "B";
}
$b = new B();
$b->echoExtendedStaticVariable(); // B

Note that you can only do this if you have access to an instance, so you can't make echoExtendedStaticVariable a static method and expect this to work.

Francis Avila
  • 31,233
  • 6
  • 58
  • 96
  • Is there any other way of doing it without creating an object? Just running the function on the class? – Alex V Dec 21 '11 at 00:49
  • Running what function on what class? In php < 5.3, a static method in a parent class has no way of knowing if it was called staticly through another class. The names are all resolved at compile time. and as @netcoder said, this is not a good design anyway! What's wrong with using instances? – Francis Avila Dec 21 '11 at 01:43
2

There is no way to do this easily in PHP 5.2 (i.e.: without explicitly overriding each method).

When you call B::echoExtendedStaticVariable, it forwards to A::echoExtendedStaticVariable, the scope changes to the one of A and all bindings about B are gone. No backtrace, no reflection, no magic constants, nothing: it all points to A.

In my opinion, static members should be avoided unless really necessary, and it is rarely the case. It renders your code difficult to extend, since dependency injection is limited and substitution is almost impossible (except in anti- patterns like Singleton).

netcoder
  • 66,435
  • 19
  • 125
  • 142