As of PHP 5.3.0, PHP implements a feature called late static bindings which
can be used to reference the called class in a context of static inheritance.
This feature was named "late static bindings" with an internal perspective in
mind. "Late binding" comes from the fact that static::
will no longer be resolved using the class where the method is defined but
it will rather be computed using runtime information.
It was also called a "static binding" as it can be used for (but is not
limited to) static method calls.
Limitations of self::
Static references to the current class like self:: or
__CLASS__ are resolved using the class in which the
function belongs, as in where it was defined:
Example #1 self:: usage
<?php class A { public static function who() { echo __CLASS__; } public static function test() { self::who(); } }
class B extends A { public static function who() { echo __CLASS__; } }
B::test(); ?>
The above example will output:
A
Late Static Bindings' usage
Late static bindings tries to solve that limitation by introducing a
keyword that references the class that was initially called at runtime.
Basically, a keyword that would allow you to reference
B from test() in the previous
example. It was decided not to introduce a new keyword but rather use
static that was already reserved.
Example #2 static:: simple usage
<?php class A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // Here comes Late Static Bindings } }
class B extends A { public static function who() { echo __CLASS__; } }
B::test(); ?>
The above example will output:
B
Note:
static:: does not work like $this for
static methods! $this-> follows the rules of
inheritance while static:: doesn't. This difference is
detailed later on this manual page.
Example #3 static:: usage in a non-static context
<?php class TestChild extends TestParent { public function __construct() { static::who(); }
public function test() { $o = new TestParent(); }
public static function who() { echo __CLASS__."\n"; } }
class TestParent { public function __construct() { static::who(); }
public static function who() { echo __CLASS__."\n"; } } $o = new TestChild; $o->test();
?>
The above example will output:
TestChild
TestParent
Note:
Late static bindings' resolution will stop at a fully resolved static call with no fallback. On the other hand, static calls using keywords like parent:: or self:: will forward the calling information.
Example #4 Forwarding and non-forwarding calls
<?php class A { public static function foo() { static::who(); }
public static function who() { echo __CLASS__."\n"; } }
class B extends A { public static function test() { A::foo(); parent::foo(); self::foo(); }
public static function who() { echo __CLASS__."\n"; } } class C extends B { public static function who() { echo __CLASS__."\n"; } }
C::test(); ?>
The above example will output:
A
C
C
Edge cases
There are lots of different ways to trigger a method call in PHP, like
callbacks or magic methods. As late static bindings base their resolution
on runtime information, it might give unexpected results in so-called edge
cases.
Example #5 Late static bindings inside magic methods
<?php class A {
protected static function who() { echo __CLASS__."\n"; }
public function __get($var) { return static::who(); } }
class B extends A {
protected static function who() { echo __CLASS__."\n"; } }