Manuel PHP

Late Static Bindings

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:

Exemple #1 self:: usage

  1. <?php
  2. class A { 
  3.    public static function who() { 
  4.       echo __CLASS__; 
  5.    } 
  6.    public static function test() { 
  7.       self::who(); 
  8.    }  
  9. }  
  10.  
  11. class B extends A { 
  12.    public static function who() { 
  13.       echo __CLASS__; 
  14.    }  
  15. }  
  16.  
  17. B::test();  
  18. ?> 

L'exemple ci-dessus va afficher :

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.

Exemple #2 static:: simple usage

  1. <?php
  2. class A { 
  3.    public static function who() { 
  4.       echo __CLASS__; 
  5.    } 
  6.    public static function test() { 
  7.       static::who(); // Here comes Late Static Bindings
  8.    }  
  9. }  
  10.  
  11. class B extends A { 
  12.    public static function who() { 
  13.       echo __CLASS__; 
  14.    }  
  15. }  
  16.  
  17. B::test();  
  18. ?> 

L'exemple ci-dessus va afficher :

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.

Exemple #3 static:: usage in a non-static context

  1. <?php
  2. class TestChild extends TestParent { 
  3.    public function __construct() { 
  4.       static::who(); 
  5.    } 
  6.  
  7.    public function test() { 
  8.       $o = new TestParent(); 
  9.    } 
  10.  
  11.    public static function who() { 
  12.       echo __CLASS__."\n"; 
  13.    }  
  14. }  
  15.  
  16. class TestParent { 
  17.    public function __construct() { 
  18.       static::who(); 
  19.    } 
  20.  
  21.    public static function who() { 
  22.       echo __CLASS__."\n"; 
  23.    }  
  24. }  
  25. $o = new TestChild;  
  26. $o->test();  
  27.  
  28. ?> 

L'exemple ci-dessus va afficher :

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.

Exemple #4 Forwarding and non-forwarding calls

  1. <?php
  2. class A { 
  3.    public static function foo() { 
  4.       static::who(); 
  5.    } 
  6.  
  7.    public static function who() { 
  8.       echo __CLASS__."\n"; 
  9.    }  
  10. }  
  11.  
  12. class B extends A { 
  13.    public static function test() { 
  14.       A::foo(); 
  15.       parent::foo(); 
  16.       self::foo(); 
  17.    } 
  18.  
  19.    public static function who() { 
  20.       echo __CLASS__."\n"; 
  21.    }  
  22. }  
  23. class C extends B { 
  24.    public static function who() { 
  25.       echo __CLASS__."\n"; 
  26.    }  
  27. }  
  28.  
  29. C::test();  
  30. ?> 

L'exemple ci-dessus va afficher :

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.

Exemple #5 Late static bindings inside magic methods

  1. <?php
  2. class A {  
  3.  
  4. protected static function who() { 
  5.       echo __CLASS__."\n";  
  6. }  
  7.  
  8. public function __get($var) { 
  9.    return static::who();  
  10. }  
  11. }  
  12.  
  13. class B extends A {  
  14.  
  15. protected static function who() { 
  16.       echo __CLASS__."\n";  
  17. }  
  18. }  
  19.  
  20. $b = new B;  
  21. $b->foo;  
  22. ?> 

L'exemple ci-dessus va afficher :

B

Remonter Remonter
L'éditeur javascript - CSS - Gentoo - Tutoriaux PHP - Tutoriels PHP - Bretagne - php - Moto - Kit graphique