Як я можу отримати ім'я класу зі статичного виклику в розширеному класі PHP?


93

У мене два класи: Actionі MyAction. Останній оголошується як:

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

Мені потрібен лише метод у Actionкласі (тільки в ньому, оскільки буде багато успадкованих класів, і я не хочу реалізовувати цей метод у всіх), який поверне ім'я класу із статичного виклику. Ось про що я кажу:

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

І коли я називаю це:

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

Але кожне оголошення в батьківському класі має доступ лише до __CLASS__змінної батьківського класу , яке має значення “Action”.

Чи можливий спосіб зробити це?

Відповіді:


176

__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

Єдина проблема для ОП полягає в тому, що ця функція ще не доступна. PHP 5.3 ще у бета-версії.
Ionuț G. Stan

3
@ Пол, спасибі! Ви щойно врятували мій день ... або ніч з get_called_class():)
Марекі

1
Я хотів би, щоб хтось міг допомогти мені з подібною проблемою . PHP-скрипт вмирає безшумно при виконанні new static();зсередини приватного статичного методу (з використанням xampp у Windows та php> 5,5). :s
Stphane

$ foo = новий MyAction; echo get_class ($ foo); Це також друкує MyAction.
sammry

41

Починаючи з версії 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

16

Це не ідеальне рішення, але воно працює на 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();
    }
}


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

0

У доступних версіях PHP немає можливості зробити те, що ви хочете. Рішення Пола Діксона єдине. Я маю на увазі приклад коду, оскільки функція пізнього статичного прив’язки, про яку він говорить, доступна з PHP 5.3, що знаходиться в бета-версії.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.