web-dev-qa-db-fra.com

Comment puis-je obtenir le nom de classe d'un appel statique dans une classe étendue PHP?

J'ai deux classes: Action et MyAction. Ce dernier est déclaré comme:

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

Tout ce dont j'ai besoin est une méthode dans la classe Action (uniquement dedans, car il y aura beaucoup de classes héritées, et je ne veux pas implémenter cette méthode dans toutes), qui renverra le nom de classe de un appel statique. Voici de quoi je parle:

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

Et quand je l'appelle:

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

Mais chaque déclaration de la classe parente n'a accès qu'à la classe parente __CLASS__ variable, qui a la valeur "Action".

Y a-t-il un moyen possible de le faire?

80
Anton

__CLASS__ renvoie toujours le nom de la classe dans laquelle il a été utilisé, donc cela n'aide pas beaucoup avec une méthode statique. Si la méthode n'était pas statique, vous pouvez simplement utiliser get_class ($ this). par exemple.

class Action {
    public function n(){
        echo get_class($this);
    }

}

class MyAction extends Action {

}

$foo=new MyAction;

$foo->n(); //displays 'MyAction'

Liaisons statiques tardives, disponibles en PHP 5.3+

Maintenant que PHP 5.3 est publié, vous pouvez utiliser liaisons statiques tardives , qui vous permettent de résoudre la classe cible pour un appel de méthode statique au moment de l'exécution plutôt que lorsqu'elle est définie) .

Bien que la fonctionnalité n'introduise pas de nouvelle constante magique pour vous indiquer le nom de classe par lequel vous avez été appelé, elle fournit une nouvelle fonction, get_called_class () qui peut vous indiquer le nom de la classe utilisée pour une méthode statique. appelé. Voici un exemple:

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


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction
166
Paul Dixon

Depuis 5.5, vous pouvez tilisez le mot clé class pour la résolution du nom de classe , ce qui serait beaucoup plus rapide que de faire des appels de fonction. Fonctionne également avec les interfaces.

// 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
37
Ian Bytchek

Ce n'est pas la solution idéale, mais cela fonctionne sur PHP <5.3.0.

Le code a été copié de 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
Jrgns

Maintenant (quand 5.3 est arrivé), c'est assez simple:

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

12
src091
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
Lulu

Il n'y a aucun moyen, dans les versions PHP PHP disponibles, de faire ce que vous voulez. La solution de Paul Dixon est la seule. Je veux dire, l'exemple de code, comme la fonction de liaisons statiques tardives dont il parle est disponible à partir de PHP 5.3, qui est en version bêta.

0
Ionuț G. Stan