phpselfderived-classstatic-classesstatic-functions

PHP: get derived class context in static function? i.e. differ between BaseClass::staticBaseFunc() vs DerivedClass::staticBaseFunc()


I have a base class with a static function. But I would like to have a way to know the actual class (could be the base class or a derived class) within whose context I am calling the static function.

For example:

<?php

class Foo
{
    static function Test() 
    { 
        $c = self::class;
        echo "Hello, I am creating a new instance of type $c";
        return new $c;
    }
}

class Bar extends Foo 
{
    public $someProperty;
}

$b = Bar::Test(); // This should do something different than Foo::Test();

?>

Note that the self::class in the Test() function always results in 'Foo' even if I'm calling it using the Bar:: context.

I understand I could override the Test() function in Bar but that's not what I want, I want to keep the implemented functionality in the base Test() function. But just with the actual static class context that I'm calling it with.

Is there a way for the above Test() function to say "I am creating a new instance of type Bar" and return a Bar instance, rather than a Foo ?


Solution

  • Let me introduced you to late static binding.

    Consider the following code, it's not exactly like yours but it highlight's the issue I believe you are facing.

    <?php
    
    class A 
    {
    
        public static $string = 'I am from class A';
    
        public static function getString()
        {
            return self::$string;
        }
    }
    
    class B extends A
    {
        public static $string = 'I am from class B';
    }
    
    B::getString(); // returns 'I am from class A' ???!
    ?>
    

    To get around this you can use late static binding to use the variable at run time context (rather than at compile time context)

    <?php
    
    class A 
    {
    
        public static $string = 'I am from class A';
    
        public static function getString()
        {
            return static::$string; // note the change here
        }
    }
    
    class B extends A
    {
        public static $string = 'I am from class B';
    }
    
    B::getString(); // returns 'I am from class B' and all is well 
    ?>
    

    Far more information than I can give you is available here: https://www.php.net/manual/en/language.oop5.late-static-bindings.php