Wie kann ich den classnnamen von einem statischen Aufruf in einer erweiterten PHP-class erhalten?

Ich habe zwei classn: Action und MyAction . Letzteres wird erklärt als:

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

Alles, was ich brauche, ist eine Methode in der Action class (nur darin, weil es viele vererbte classn geben wird, und ich möchte diese Methode nicht in allen implementieren), die den classnnamen von einem statischen Aufruf zurückgibt. Hier ist, worüber ich rede:

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

Und wenn ich es nenne:

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

Jede Deklaration in der übergeordneten class hat jedoch nur Zugriff auf die Variable __CLASS__ der übergeordneten class, die den Wert “Action” hat.

Gibt es einen möglichen Weg dies zu tun?

__CLASS__ immer den Namen der class zurück, in der sie verwendet wurde, daher ist es bei einer statischen Methode nicht sehr hilfreich. Wenn die Methode nicht statisch wäre, könnten Sie einfach get_class ($ this) verwenden. z.B

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

Späte statische Bindungen, verfügbar in PHP 5.3+

Jetzt, da PHP 5.3 veröffentlicht ist, können Sie späte statische Bindungen verwenden , mit denen Sie die Zielklasse für einen statischen Methodenaufruf zur Laufzeit und nicht bei der Definition auflösen können.

Während das Feature keine neue magische Konstante einführt, um Ihnen den classnnamen zu nennen, durch den Sie aufgerufen wurden, bietet es eine neue function, get_called_class (), die Ihnen den Namen der class, in der eine statische Methode aufgerufen wurde, mitteilen kann.

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

Seit 5.5 können Sie das class für die Auflösung des classnnamens verwenden , was viel schneller ist als functionsaufrufe. functioniert auch mit Schnittstellen.

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

Es ist nicht die ideale Lösung, aber es funktioniert mit PHP <5.3.0.

Der Code wurde von septuro.com kopiert

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

Jetzt (wenn 5.3 angekommen ist) ist es ziemlich einfach:

http://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(); 

Es gibt keine Möglichkeit, in den verfügbaren PHP-Versionen zu tun, was Sie wollen. Paul Dixons Lösung ist die einzige. Ich meine das Codebeispiel, da das späte statische Binding-Feature, über das er spricht, ab PHP 5.3 verfügbar ist, das sich in der Beta-Version befindet.