Faking late static binding in PHP

November 18, 2009

PHP 5.3 brings lots of long awaited features to the language, including closures, late static binding and namespaces. Unfortunately 5.3 still isn’t widely available, so some of us are stuck with older version of the language that lack these great new features.

One feature I miss all the time is late static binding, or LSB. The lack of LSB means that you can’t tell tell which class in your class hierarchy was invoked when calling a static method. Here’s a simple example:

class class0 {
  public static function getName() {
      echo __CLASS__ . "\n";
  }
}

class class1 extends class0 {}

class class2 extends class1 {}

class0::getName(); // -> "class0"
class1::getName(); // -> "class0"
class2::getName(); // -> "class0"

Notice that all three method calls output “class0″, the name of the base class. There is no way to tell which class the static method was called on, and in some situations that is information we need to know.

So what can we do? One obvious solution is to re-implement the method in every subclass. This doesn’t pose much of a problem for a method as simple as the one in our example, but in reality our method is likely to be much more complex, and implementing it in every subclass will lead to lots of duplication. If we ever need to make changes to the method then changes will need to be made to every subclass too. Not fun!

And alternative solution is to have every subclass invoke the parent method, passing in the class name (or whatever variable we’re interested in). It requires only a couple of extra lines per subclass, rather than repeating the whole method. Any changes now only need to be made in one place. Here’s the code:

class class0 {
  public static function getName($class = __CLASS__) {
      echo "$class\n";
  }
}

class class1 extends class0 {
  public static function getName($class = __CLASS__) {
      return parent::getName($class);
  }
}

class class2 extends class1 {
  public static function getName($class = __CLASS__) {
      return parent::getName($class);
  }
}

class0::getName(); // -> "class0"
class1::getName(); // -> "class1"
class2::getName(); // -> "class2"

In PHP5.3 we can use the new get_called_class(), so the code becomes much cleaner:

class class0 {
  public static function getName() {
      echo get_called_class() . "\n";
  }
}

class class1 extends class0 {}

class class2 extends class1 {}

class0::getName(); // -> "class0"
class1::getName(); // -> "class1"
class2::getName(); // -> "class2"

2 Comments »

  1. Wait, so you aren’t using the static keyword (http://php.net/manual/en/language.oop5.late-static-bindings.php) because 5.3 isn’t widely available, so instead you use get_called_class() to emulate the static keyword, despite the fact that get_called_class() is a php 5.3 function only?

    Comment by Daniel — November 18, 2009 @ 10:46 pm

  2. Hi Daniel,

    The last example is a PHP5.3 example, which makes use of get_called_class method, part of the LSB additions. The example is there to show how we can achieve what we want in PHP5.3

    The example before that is how I propose to “fake” LSB in PHP pre 5.3. Sorry if that wasn’t clear enough.

    Thanks, Ben

    Comment by Ben — November 18, 2009 @ 11:04 pm

RSS feed for comments on this post.

Leave a comment