Late Static Binding in PHP
Tags: php
Published: 2020-01-28 09:41:21

---
title: Late Static Binding in PHP
published: true
tags: php
canonical_url: https://codeinphp.github.io/post/late-static-binding-in-php/
---

Let'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.

 ![](http://feeds.feedburner.com/~r/codeinphpfeed/~4/SjpISpV1Dj0)