The compiler performs a process called binding when an object is assigned to an object variable. The early binding (static binding) refers to compile time binding and late binding (dynamic binding) refers to runtime binding.
This is called late static binding. This feature of late static binding was introduced in PHP 5.3 and above, previous versions will show a fatal error.
In addition to this, any static function or variable is usually executed during runtime and not during compile time. Hence, if a value needs to be dynamically assigned to a variable that is static, it happens during runtime, and this is known as late static binding.
PHP Classes and Objects Dynamic Binding Dynamic binding, also referred as method overriding is an example of run time polymorphism that occurs when multiple classes contain different implementations of the same method, but the object that the method will be called on is unknown until run time.
You definitely need to read Late Static Bindings in the PHP manual. However, I'll try to give you a quick summary.
Basically, it boils down to the fact that the self
keyword does not follow the same rules of inheritance. self
always resolves to the class in which it is used. This means that if you make a method in a parent class and call it from a child class, self
will not reference the child as you might expect.
Late static binding introduces a new use for the static
keyword, which addresses this particular shortcoming. When you use static
, it represents the class where you first use it, ie. it 'binds' to the runtime class.
Those are the two basic concepts behind it. The way self
, parent
and static
operate when static
is in play can be subtle, so rather than go in to more detail, I'd strongly recommend that you study the manual page examples. Once you understand the basics of each keyword, the examples are quite necessary to see what kind of results you're going to get.
From PHP: Late Static Bindings - Manual:
As of PHP 5.3.0, PHP implements a feature called late static binding which can be used to reference the called class in the context of static inheritance.
Late static binding tries to solve that limitation by introducing a keyword that references the class that was initially called at runtime. ... It was decided not to introduce a new keyword, but rather use
static
that was already reserved.
Let's see an example:
<?php
class Car
{
public static function run()
{
return static::getName();
}
private static function getName()
{
return 'Car';
}
}
class Toyota extends Car
{
public static function getName()
{
return 'Toyota';
}
}
echo Car::run(); // Output: Car
echo Toyota::run(); // Output: Toyota
?>
Late static bindings work by storing the class named in the last "non-forwarding call". In case of static method calls, this is the class explicitly named (usually the one on the left of the
::
operator); in case of non-static method calls, it is the class of the object. A "forwarding call" is a static one that is introduced byself::
,parent::
,static::
, or, if going up in the class hierarchy,forward_static_call()
. The functionget_called_class()
can be used to retrieve a string with the name of the called class andstatic::
introduces its scope.
There is not very obvious behavior:
The following code produces 'alphabeta'.
class alpha {
function classname(){
return __CLASS__;
}
function selfname(){
return self::classname();
}
function staticname(){
return static::classname();
}
}
class beta extends alpha {
function classname(){
return __CLASS__;
}
}
$beta = new beta();
echo $beta->selfname(); // Output: alpha
echo $beta->staticname(); // Output: beta
However, if we remove the declaration of the classname function from the beta class, we get 'alphaalpha' as the result.
I'm quoting from the book: "PHP Master write cutting-edge code".
Late static binding was a feature introduced with php 5.3. It allows us to inherit static methods from a parent class, and to reference the child class being called.
This means you can have an abstract class with static methods, and reference the child class's concrete implementations by using the static::method() notation instead of the self::method().
Feel free to take a look at the official php documentation as well: http://php.net/manual/en/language.oop5.late-static-bindings.php
The clearest way to explain Late Static Binding is with a practicle example. I'm using it in a Template method pattern. See below.
abstract class AbstractTemplate {
public const AWESOME_LIST = [''];
public function someFunction(): void {
$awesomeList = $this->getAwesomeList();
// OUTPUT: ['harry','henk','john'];
var_dump($awesomeList);
}
/**
* This function gets static constants from CHILD classes
*/
public function getAwesomeList(): array
{
return static::AWESOME_LIST;
}
}
class ConcreteTemplate extends AbstractTemplate {
public const AWESOME_LIST = ['harry','henk','john'];
public function someFunction(): void {
parent::someFunction();
}
}
$concreteTemplate = new ConcreteTemplate();
$concreteTemplate->someFunction();
Notice the static
keyword in method getAwesomeList
.
Let's change a bit now:
public function getAwesomeList(): array
{
return self::AWESOME_LIST;
}
The output of the var_dump
at someFunction
would be:
array (size=1)
0 => string '' (length=0)
The static
keyword is used in a Singleton design pattern.
See link: https://refactoring.guru/design-patterns/singleton/php/example
The simplest example to show the difference.
Note, self::$c
class A
{
static $c = 7;
public static function getVal()
{
return self::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 7
Late static binding, note static::$c
class A
{
static $c = 7;
public static function getVal()
{
return static::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 8
Looking at it from a "why would I use this?" perspective, it's basically a way to change the context from which the static method is being interpreted/run.
With self
, the context is the one where you defined the method originally. With static
, it's the one you're calling it from.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With