Depuis PHP 5.3.0, PHP implémente une fonctionnalité appelée late static bindings, en français la résolution statique à la volée, qui est utilisée pour choisir la classe appelée dans le cadre de l'héritage de méthodes statiques.
Cette fonctionnalité a été baptisée "late static bindings", d'un point de vue interne. "Late binding", littéralement compilation tardive, vient du fait que les éléments static:: ne seront plus résolus en utilisant la classe où la méthode a été définie, mais celle qui est active durant l'exécution. L'adjectif statique a été ajouté car ce problème s'applique aux méthodes statiques, mais pas seulement.
Les références à la clsse courante, avec self:: ou __CLASS__ sont résolues en utilisant la classe à qui appartiennent les fonctions, où elles ont été définies :
Exemple #1 Utilisation de self::
<?php
class A {
public static function qui() {
echo __CLASS__;
}
public static function test() {
self::qui();
}
}
class B extends A {
public static function qui() {
echo __CLASS__;
}
}
B::test();
?>
L'exemple ci-dessus va afficher :
A
La résolution statique à la volée essaie de dépasser cette limitation en introduisant un mot clé qui fait référence à la classe qui est appelée durant l'exécution. Simplement, ce mot-clé vous permet de faire référence à B depuis test(), dans l'exemple précédent. Il a été décidé de ne pas introduite de nouveau mot clé, mais plutôt d'utiliser le mot static qui était déjà réservé.
Exemple #2 Utilisation simple de static::
<?php
class A {
public static function qui() {
echo __CLASS__;
}
public static function test() {
static::qui(); // Ici, résolution à la volée
}
}
class B extends A {
public static function qui() {
echo __CLASS__;
}
}
B::test();
?>
L'exemple ci-dessus va afficher :
B
Note: static:: ne fonctionne pas comme $this pour les méthodes statiques. $this-> suit les règles de l'héritage alors que static:: ne les suit pas. Cette différence est détaillée plus tard dans le manuel.
Exemple #3 Utilisation de static:: dans un contexte non statique
<?php
class TestChild extends TestParent {
public function __construct() {
static::qui();
}
public function test() {
$o = new TestParent();
}
public static function qui() {
echo __CLASS__."\n";
}
}
class TestParent {
public function __construct() {
static::qui();
}
public static function qui() {
echo __CLASS__."\n";
}
}
$o = new TestChild;
$o->test();
?>
L'exemple ci-dessus va afficher :
TestChild TestParent
Note: La résolution des statiques à la volée va s'arrêter à un appel statique complètement résolu. D'un autre coté, les appels à statique en utilisant un mot-clé comme parent:: ou self:: va transmettre l'information appelante.
Exemple #4 Appel avec ou sans transmission
<?php
class A {
public static function foo() {
static::qui();
}
public static function qui() {
echo __CLASS__."\n";
}
}
class B extends A {
public static function test() {
A::foo();
parent::foo();
self::foo();
}
public static function qui() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function qui() {
echo __CLASS__."\n";
}
}
C::test();
?>L'exemple ci-dessus va afficher :
A C C
Il y a de nombreuses solutions pour lancer un appel à une méthode en PHP, comme des fonctions de rappels, ou des méthodes magiques. La résolution statique à la volée qui effectue son travail à l'exécution, il peut y avoir des cas particuliers qui donnent des résultats inattendus.
Exemple #5 Résolution statique à la volée dans une méthod magique
<?php
class A {
protected static function qui() {
echo __CLASS__."\n";
}
public function __get($var) {
return static::qui();
}
}
class B extends A {
protected static function qui() {
echo __CLASS__."\n";
}
}
$b = new B;
$b->foo;
?>
L'exemple ci-dessus va afficher :
B