How can I get the classname from a static call in an extended PHP class?

67,831

Solution 1

__CLASS__ always returns the name of the class in which it was used, so it's not much help with a static method. If the method wasn't static you could simply use get_class($this). e.g.

class Action {
    public function n(){
        echo get_class($this);
    }

}

class MyAction extends Action {

}

$foo=new MyAction;

$foo->n(); //displays 'MyAction'

Late static bindings, available in PHP 5.3+

Now that PHP 5.3 is released, you can use late static bindings, which let you resolve the target class for a static method call at runtime rather than when it is defined.

While the feature does not introduce a new magic constant to tell you the classname you were called through, it does provide a new function, get_called_class() which can tell you the name of the class a static method was called in. Here's an example:

Class Action {
    public static function n() {
        return get_called_class();
    }
}


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction

Solution 2

Since 5.5 you can use class keyword for the class name resolution, which would be a lot faster than making function calls. Also works with interfaces.

// C extends B extends A

static::class  // MyNamespace\ClassC when run in A
self::class    // MyNamespace\ClassA when run in A
parent::class  // MyNamespace\ClassB when run in C
MyClass::class // MyNamespace\MyClass

Solution 3

It's not the ideal solution, but it works on PHP < 5.3.0.

The code was copied from septuro.com

if(!function_exists('get_called_class')) {
    class class_tools {
        static $i = 0;
        static $fl = null;

        static function get_called_class() {
            $bt = debug_backtrace();

            if (self::$fl == $bt[2]['file'].$bt[2]['line']) {
                self::$i++;
            } else {
                self::$i = 0;
                self::$fl = $bt[2]['file'].$bt[2]['line'];
            }

            $lines = file($bt[2]['file']);

            preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
                $lines[$bt[2]['line']-1],
                $matches);

            return $matches[1][self::$i];
        }
    }

    function get_called_class() {
        return class_tools::get_called_class();
    }
}

Solution 4

Now (when 5.3 has arrived) it's pretty simple:

http://php.net/manual/en/function.get-called-class.php

Solution 5

class MainSingleton { 
  private static $instances = array(); 
  private static function get_called_class() {
    $t = debug_backtrace();
    return $t[count($t)-1]["class"];
  }  

  public static function getInstance() { 
    $class = self::get_called_class();
    if(!isset(self::$instances[$class]) ) { 
      self::$instances[$class] = new $class; 
    } 
    return self::$instances[$class]; 
  } 

}

class Singleton extends MainSingleton { 
  public static function getInstance()
  {
    return parent::getInstance();
  }     
  protected function __construct() { 
    echo "A". PHP_EOL; 
  } 

  protected function __clone() {} 

  public function test() { 
    echo " * test called * "; 
  } 
} 

Singleton::getInstance()->test(); 
Singleton::getInstance()->test();
Share:
67,831
Anton
Author by

Anton

Scala, R, data.

Updated on August 23, 2020

Comments

  • Anton
    Anton over 3 years

    I have two classes: Action and MyAction. The latter is declared as:

    class MyAction extends Action {/* some methods here */}
    

    All I need is method in the Action class (only in it, because there will be a lot of inherited classes, and I don’t want to implement this method in all of them), which will return classname from a static call. Here is what I’m talking about:

    Class Action {
     function n(){/* something */}
    }
    

    And when I call it:

    MyAction::n(); // it should return "MyAction"
    

    But each declaration in the parent class has access only to the parent class __CLASS__ variable, which has the value “Action”.

    Is there any possible way to do this?

  • user5880801
    user5880801 over 15 years
    The only problem for the OP is that the feature is not yet available. PHP 5.3 is yet in beta.
  • Marecky
    Marecky over 11 years
    @Paul, thanks! You just saved my day... or night with get_called_class() :)
  • Ian Bytchek
    Ian Bytchek over 9 years
    Now (when 5.5 has arrived (a long time ago)) it's even simpler: stackoverflow.com/a/25694818/458356
  • Stphane
    Stphane over 7 years
    I wish someone could help me with a similar issue. PHP script dies silently upon executing new static(); from inside a private static method (using xampp on windows and php>5.5). :s
  • sammry
    sammry almost 6 years
    $foo=new MyAction; echo get_class($foo); This also prints MyAction.
  • Alexander Kucheryuk
    Alexander Kucheryuk over 3 years
    get_class and ::class may return different results (case sensitivity). Details are here - stackoverflow.com/questions/34118725/…
  • Mahdi
    Mahdi about 3 years
    use static::class