Как я могу получить имя класса из статического вызова в расширенном классе PHP?

У меня есть два класса: Action и MyAction . Последняя заявляется как:

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

Все, что мне нужно, это метод в классе Action (только в нем, потому что будет много унаследованных классов, и я не хочу реализовать этот метод во всех них), который вернет имя класса из статического вызова. Вот о чем я говорю:

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

И когда я это называю:

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

Но каждое объявление в родительском классе имеет доступ только к переменной родительского класса __CLASS__ , которая имеет значение «Действие».

Есть ли способ сделать это?

__CLASS__ всегда возвращает имя класса, в котором он был использован, поэтому он не очень помогает статическому методу. Если метод не был статичным, вы можете просто использовать get_class ($ this). например

 class Action { public function n(){ echo get_class($this); } } class MyAction extends Action { } $foo=new MyAction; $foo->n(); //displays 'MyAction' 

Поздние статические привязки, доступные в PHP 5.3+

Теперь, когда выпущен PHP 5.3, вы можете использовать поздние статические привязки , которые позволяют разрешать целевой класс для вызова статического метода во время выполнения, а не когда он определен.

Хотя функция не вводит новую магическую константу, чтобы сообщить вам имя класса, с которым вы были вызваны, она предоставляет новую функцию get_called_class (), которая может указать вам имя класса, в который был вызван статический метод. Вот пример:

 Class Action { public static function n() { return get_called_class(); } } class MyAction extends Action { } echo MyAction::n(); //displays MyAction 

Начиная с версии 5.5 вы можете использовать ключевое слово class для разрешения имени класса , которое было бы намного быстрее, чем выполнение вызовов функций. Также работает с интерфейсами.

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

Это не идеальное решение, но оно работает на PHP <5.3.0.

Код скопирован с 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(); } } 

Теперь (когда 5.3 прибыл) это довольно просто:

http://ua.php.net/manual/en/function.get-called-class.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(); 

В доступных версиях PHP нет способа делать то, что вы хотите. Решение Пауля Диксона единственное. Я имею в виду, пример кода, поскольку последняя функция статических привязок, о которой он говорит, доступна с PHP 5.3, которая находится в бета-версии.