От PHP 5.3.0 в PHP е реализирано късно статично свързване, което може да се използва за обръщане към извикания клас в контекста на статичното наследяване.
Тази възможност неслучайно е наречена "късно статично свързване". "Късно свързване" идва от факта, че static:: вече няма да сочи към класа, в който е дефиниран методът, а ще бъде изчисляван на базата на информацията по време на изпълнение на скрипта. Също така е наречено "статично свързване", тъй като може да се използва (без да е ограничено само в тази употреба) за извикване на статични методи.
Статичните референции към текущия клас като self:: и __CLASS__ се извикват на базата на това на кой клас принадлежи методът, т.е. къде е дефиниран:
Example #1 Употреба на self::
<?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();
?>
Примерът по-горе ще изведе:
A
С късното статично свързване се прави опит да се премахне това ограничение чрез въвеждането на нова ключова дума, която да сочи към класа, който първоначално е бил извикан по време на изпълнение. На практика това е ключовата дума, която би позволила да се извика B от test() в предишния пример. Веше решено вместо да се въвежда нова ключова дума, да се използва static, която така или иначе вече е запазена.
Example #2 Проста употреба на static::
<?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();
?>
Примерът по-горе ще изведе:
B
Забележка: static:: не работи еквивалентно на $this за статични методи! $this-> следва правилата на наследяването, за разлика от static::. Тази разлика е обяснена по-подробно малко по-късно.
Example #3 Употреба на static:: в нестатичен контекст
<?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();
?>
Примерът по-горе ще изведе:
TestChild TestParent
Забележка: Решението кой метод да се изпълни при късното статично свързване ще бъде взето при напълно определено статично извикване, без връщане. От друга страна, статичните извиквани посредством ключовите думи като parent:: и self:: ще препратят извикващата информация.
Example #4 Препращащи и непрепращащи извиквания
<?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();
?>Примерът по-горе ще изведе:
A C C
Съществуват редица различни начини да се извика метод в PHP, като например - обратни извиквания и вълшебни методи. Тъй като, при късното статично свързване, решението кой метод да се изпълни се базира на информацията по време на изпълнение, това може да доведе до неочаквани резултати при т.н. крайни случаи.
Example #5 Късно статично свързване във вълшебни методи
<?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";
}
}
$b = new B;
$b->foo;
?>
Примерът по-горе ще изведе:
B