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

PhpOopInheritance

Php Problem Overview


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?

Php Solutions


Solution 1 - Php

__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 - Php

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 - Php

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 - Php

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

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

Solution 5 - Php

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();

Solution 6 - Php

(PHP 5 >= 5.3.0, PHP 7)
get_called_class — The "Late Static Binding" class name

<?php

class Model
{
  public static function find()
  {
    return get_called_class();
  }
}

class User extends Model
{
}


echo User::find();

this link might be helpfull

Solution 7 - Php

There is no way, in the available PHP versions, to do what you want. Paul Dixon's solution is the only one. I mean, the code example, as the late static bindings feature he's talking about is available as of PHP 5.3, which is in beta.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAntonView Question on Stackoverflow
Solution 1 - PhpPaul DixonView Answer on Stackoverflow
Solution 2 - PhpIan BytchekView Answer on Stackoverflow
Solution 3 - PhpJrgnsView Answer on Stackoverflow
Solution 4 - Phpsrc091View Answer on Stackoverflow
Solution 5 - PhpLuluView Answer on Stackoverflow
Solution 6 - PhpBiswajit BiswasView Answer on Stackoverflow
Solution 7 - PhpIonuț G. StanView Answer on Stackoverflow