Get "PHP 8 in a Nuthshell" (Soon includes PHP 8.4)
Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

Late static binding in PHP - What, How & When

The inheritence tree in PHP quickly gets dirty if you’re using mix of static and non-static methods into your classes and the inheritence is deeply nested.

Take from example here.

<?php

class Alpha 
{
    public static function getClassname() 
    {
        echo __CLASS__;
    }

    public static function printClass() 
    {
        self::getClassname();
    }
}

class Beta extends Alpha 
{
    public static function getClassname() 
    {
        echo __CLASS__;
    }
}

Beta::printClass();

// Alpha
?>

Ideally, if you run above code, you’d expect it to obviously print Beta but instead it’ll print Alpha. Why? Because static references to the current class like self:: or __CLASS__ are resolved using the class in which the function belongs or in other words self keyword does not follow the same rules of inheritance. self always resolves to the class in which it is used. If you want the desired result, you’ll need to use a feature called “Late static binding”.

What is late static binding?

Late static bindings in PHP is a feature which can be used to reference the called class in a context of static inheritance.

Essentially, 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 by self::, parent::, static::, or, if going up in the class hierarchy, forward_static_call(). The function get_called_class() can be used to retrieve a string with the name of the called class and static:: introduces its scope.

Let’s see how we can apply late static binding in the previous example and get our desired result.

<?php

class Alpha 
{
    public static function getClassname() 
    {
        echo __CLASS__;
    }

    public static function printClass() 
    {
        static::getClassname();
    }
}

class Beta extends Alpha 
{
    public static function getClassname() 
    {
        echo __CLASS__;
    }
}

Beta::printClass();

// Beta
?>

Running above PHP will now print Beta, because as you can see static::getClassname() will bring late static binding into the picture and now it will reference the class that was initially called at runtime which in our case is class Beta.

“Late binding” comes from the fact that static:: will not be resolved using the class where the method is defined but it will rather be computed using runtime information. It’s also called a “static binding” as it can be used for (but is not limited to) static method calls. Another important thing to note here is that static:: can only refer to static properties.

static references calling classes scope.

Additionally, you can use get_called_class() method which returns the class on which the static method is called. Check it here.

<?php

class Alpha 
{
    public static function printClass() 
    {
        var_dump(get_called_class());
    }
}

class Beta extends Alpha
{

}

Beta::printClass(); // Beta
Alpha::printClass(); // Alpha

?>

Late static binding on const

Late static binding would work the same way it is working for static methods. i.e. PHP will resolve the constant based on the fact that how it is been called.

<?php

class Alpha 
{
    const MY_CONST = false;

    public function selfConst() 
    {
        return self::MY_CONST;
    } 

    public function staticConst() 
    {
        return static::MY_CONST;
    } 
}

class Beta extends Alpha 
{
   const MY_CONST = true;
}

$beta = new Beta();
echo $beta->selfConst() ? 'yes' : 'no'; // prints "no"
echo $beta->staticConst() ? 'yes' : 'no'; // prints "yes"

?>

In order for late static binding to work on constant, it need not necessarily be static unlike methods as you can see in the example above.

A practical example

Here’s a practical example to understand late static binding better.

class Model 
{
    public static function find($id) 
    {
        return DB::table(static::$table)->where('id', $id)->get();
    }
}

class User extends Model 
{
    protected static $table = 'users';
}

$user = User::find(1); // Uses the 'users' table

As you can see, we’re using late static binding to get the table name (from the child class) for the find method. This way, we can use the same method for all the models without having to override it in each model.

When to use late static binding

Late static binding can be used for the following scenarios:

  • When you’ve a functionality in your application that varies over the class hierarchy.
  • When the methods in which the functionality is implemented has the same signature over the hierarchy.
  • It can be used to create static factory patterns using static method overloading to prevent requiring additional factory classes.
Learn the fundamentals of PHP 8 (including 8.1, 8.2, and 8.3), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

Like this article?

Buy me a coffee

👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.

Comments?