Как я могу получить имя класса из статического вызова в расширенном классе PHP?
У меня есть два класса: Action
и MyAction
. Последний объявляется как:
class MyAction extends Action {/* some methods here */}
Все, что мне нужно - это метод в классе Action
(только в нем, потому что будет много унаследованных классов, и я не хочу реализовать этот метод во всех них), который будет возвращать имя класса из статического вызов. Вот что я говорю о:
Class Action {
function n(){/* something */}
}
И когда я это называю:
MyAction::n(); // it should return "MyAction"
Но каждое объявление в родительском классе имеет доступ только к переменной родительского класса __CLASS__
, которая имеет значение "Действие".
Есть ли способ сделать это?
Ответы
Ответ 1
__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
Ответ 2
Начиная с версии 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
Ответ 3
Это не идеальное решение, но оно работает на 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();
}
}
Ответ 4
Теперь (когда 5.3 прибыл) это довольно просто:
http://ua.php.net/manual/en/function.get-called-class.php
Ответ 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();
Ответ 6
В доступных версиях PHP нет способа делать то, что вы хотите. Решение Пол Диксон - единственное. Я имею в виду, что пример кода, поскольку функция поздних статических привязок, о которой он говорит, доступна в PHP 5.3, которая находится в бета-версии.