Frage Wie kann ich den Klassennamen von einem statischen Aufruf in einer erweiterten PHP-Klasse erhalten?


Ich habe zwei Klassen: 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 Klasse (nur darin, weil es viele vererbte Klassen geben wird, und ich möchte diese Methode nicht in allen implementieren), die den Klassennamen 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 Klasse hat jedoch nur Zugriff auf die übergeordnete Klasse __CLASS__ Variable, die den Wert "Aktion" hat.

Gibt es einen möglichen Weg dies zu tun?


75
2018-02-03 11:04


Ursprung


Antworten:


__CLASS__ gibt immer den Namen der Klasse zurück, in der es verwendet wurde, daher hilft eine statische Methode nicht viel. Wenn die Methode nicht statisch wäre, könnten Sie einfach verwenden get_klasse($ das). 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, wo PHP 5.3 veröffentlicht ist, können Sie verwenden späte statische Bindungen, mit dem 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 Klassennamen zu nennen, durch den Sie aufgerufen wurden, bietet es eine neue Funktion, get_called_class () Das kann Ihnen den Namen der Klasse sagen, in der eine statische Methode aufgerufen wurde. Hier ein Beispiel:

Class Action {
    public static function n() {
        return get_called_class();
    }
}


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction

155
2018-02-03 11:16



Seit 5.5 kannst du benutzen class Schlüsselwort für die Auflösung des Klassennamens, das wäre viel schneller als Funktionsaufrufe. Funktioniert 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

30
2017-09-05 22:28



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

Der Code wurde kopiert 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();
    }
}

16
2017-10-09 06:07



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

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


12
2017-09-27 12:36



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

2
2018-02-14 20:16



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.


0
2018-02-03 11:27