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

90

Ich habe zwei Klassen: Actionund MyAction. Letzteres wird erklärt als:

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

Alles, was ich brauche, ist eine Methode in der ActionKlasse (nur darin, da es viele geerbte Klassen gibt und ich diese Methode nicht in allen implementieren möchte), die den Klassennamen von einem statischen Aufruf zurückgibt. Hier ist, worüber ich spreche:

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 Klassenvariable __CLASS__, die den Wert "Aktion" hat.

Gibt es eine Möglichkeit, dies zu tun?

Anton
quelle

Antworten:

174

__CLASS__Gibt immer den Namen der Klasse 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+

Nach der Veröffentlichung von PHP 5.3 können Sie späte statische Bindungen verwenden , mit denen Sie die Zielklasse für einen statischen Methodenaufruf zur Laufzeit auflösen können, anstatt wenn er definiert ist.

Während die Funktion keine neue magische Konstante einführt, um Ihnen den Klassennamen mitzuteilen, durch den Sie aufgerufen wurden, bietet sie eine neue Funktion, get_called_class (), die Ihnen den Namen der Klasse mitteilen kann, 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
Paul Dixon
quelle
Das einzige Problem für das OP ist, dass die Funktion noch nicht verfügbar ist. PHP 5.3 befindet sich noch in der Beta.
Ionuț G. Stan
3
@ Paul, danke! Du hast gerade meinen Tag gerettet ... oder die Nacht mit get_called_class():)
Marecky
1
Ich wünschte, jemand könnte mir bei einem ähnlichen Problem helfen . Das PHP-Skript stirbt stillschweigend, wenn es new static();aus einer privaten statischen Methode ausgeführt wird (unter Verwendung von xampp unter Windows und PHP> 5.5). :s
Stphane
$ foo = neue MyAction; echo get_class ($ foo); Dadurch wird auch MyAction gedruckt.
Sammry
40

Seit 5.5 können Sie verwenden classSchlüsselwort für den Klassennamen Auflösung , die viel schneller sein würde als Funktion Anrufe. 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
Ian Bytchek
quelle
16

Es ist nicht die ideale Lösung, aber es funktioniert unter 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();
    }
}
Jrgns
quelle
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();
Lulu
quelle
0

In den verfügbaren PHP-Versionen gibt es keine Möglichkeit, das zu tun, was Sie wollen. Paul Dixons Lösung ist die einzige. Ich meine, das Codebeispiel, da die Funktion für späte statische Bindungen, von der er spricht, ab PHP 5.3 verfügbar ist, das sich in der Beta befindet.

Ionuț G. Stan
quelle
0

(PHP 5> = 5.3.0, PHP 7)
get_called_class - Der Klassenname "Late Static Binding"

<?php

class Model
{
  public static function find()
  {
    return get_called_class();
  }
}

class User extends Model
{
}


echo User::find();

Dieser Link könnte hilfreich sein

Biswajit Biswas
quelle