Late Static Binding in PHP
Sarfraz Ahmed April 23, 2015 03:54 PMLet's jump into an example up front to understand the concept. Let's create two classes parent and child which would tell us the name of the object using getName()
method:
class Animal {
protected $name = 'Animal';
public function getName() {
return $this->name;
}
}
Let's extend the Animal
class so we can use its getName()
method without repeating it in child class. We will only need the $name
variable in child class to get it's name:
class Cat extends Animal {
protected $name = 'Cat';
}
Now we expect to get names of each object, let's do so:
$animal = new Animal;
$cat = new Cat;
echo $animal->getName(); // Animal
echo $cat->getName(); // Cat
And we successfully get Animal
and Cat
echoed out. But now let's modify code a bit so that we can use those classes without creating their instances with the help of static
keyword (eg global state):
class Animal {
protected static $name = 'Animal';
public static function getName() {
return self::$name;
}
}
class Cat extends Animal {
protected static $name = 'Cat';
}
echo Animal::getName(); // Animal
echo Cat::getName(); // Animal
Noticed the problem ? We wanted to see Animal
and Cat
to be echoed out like previous example but in both cases it said Animal
not Cat
.
The reason why in previous example things worked the way expected is because we explicitly created new instances of both classes using new
keyword and PHP knew which class and method to use. This is not the case in second static example. In the second example, we are using the self
keyword which always resolves to current class where it is called. This is reason why the name for the Cat
class wasn't echoed out.
So how do we get the name of cat ? Here are few ways.
By Repeating Same Code In Child Class
class Animal {
protected static $name = 'Animal';
public static function getName() {
return self::$name;
}
}
class Cat extends Animal {
protected static $name = 'Cat';
public static function getName() {
return self::$name;
}
}
echo Animal::getName(); // Animal
echo Cat::getName(); // Cat
This works but it defeats the purpose of inheritance. What is the point of extending Animal
class when we need to repeat same code in child class ? This isn't ideal.
By Using get_called_class()
class Animal {
protected static $name = 'Animal';
public static function getName() {
$class = get_called_class();
return $class::$name;
}
}
class Cat extends Animal {
protected static $name = 'Cat';
}
echo Animal::getName(); // Animal
echo Cat::getName(); // Cat
This is better and works for our purpose.
By Using static
keyword
PHP 5.3 introduced the static
keyword to help deal with this issue. Before that, get_called_class()
was what was used. Let's get the expected result using static
keyword:
class Animal {
protected static $name = 'Animal';
public static function getName() {
return static::$name;
}
}
class Cat extends Animal {
protected static $name = 'Cat';
}
echo Animal::getName(); // Animal
echo Cat::getName(); // Cat
And this works fine too. These days using static
keyword seems to be common practice instead of get_called_class()
to deal with this issue though get_called_class()
has many other uses too.
So in simple words, late static binding is something that helps us correctly resolve to static classes at run time. So when we use self
keyword, PHP checks it at compile time which class to bind the method call to but when we use static
keyword, PHP would check it late eg it would determine which class to use and bind method call to at runtime. Doing it at runtime is what helps PHP determine which class was meant.