Jak mogę uzyskać nazwę klasy z wywołania statycznego w rozszerzonej klasie PHP?

93

Mam dwie klasy: Actioni MyAction. Ten ostatni jest deklarowany jako:

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

Potrzebuję tylko metody w Actionklasie (tylko w niej, ponieważ klas dziedziczonych będzie dużo, a nie chcę implementować tej metody we wszystkich), która zwróci classname z wywołania statycznego. Oto o czym mówię:

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

A kiedy to nazywam:

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

Ale każda deklaracja w klasie nadrzędnej ma dostęp tylko do __CLASS__zmiennej klasy nadrzędnej , która ma wartość „Akcja”.

Czy można to zrobić?

Anton
źródło

Odpowiedzi:

176

__CLASS__zawsze zwraca nazwę klasy, w której został użyty, więc nie jest to zbyt pomocne przy metodzie statycznej. Jeśli metoda nie była statyczna, możesz po prostu użyć get_class ($ this). na przykład

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

}

class MyAction extends Action {

}

$foo=new MyAction;

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

Późne wiązania statyczne, dostępne w PHP 5.3+

Teraz, gdy PHP 5.3 zostało wydane, możesz używać późnych wiązań statycznych , które pozwalają rozstrzygać klasę docelową dla wywołania metody statycznej w czasie wykonywania, a nie wtedy, gdy jest zdefiniowana.

Chociaż funkcja nie wprowadza nowej magicznej stałej informującej o nazwie klasy, przez którą zostałeś wywołany, udostępnia nową funkcję, get_called_class (), która może podać nazwę klasy, do której została wywołana metoda statyczna. Oto przykład:

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


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction
Paul Dixon
źródło
Jedynym problemem dla PO jest to, że funkcja nie jest jeszcze dostępna. PHP 5.3 jest jeszcze w wersji beta.
Ionuț G. Stan
3
@Paul, dzięki! Właśnie uratowałeś mój dzień ... lub noc z get_called_class():)
Marecky
1
Chciałbym, żeby ktoś mógł mi pomóc w podobnej sprawie . Skrypt PHP cichnie umiera po wykonaniu new static();z wnętrza prywatnej metody statycznej (przy użyciu xampp w systemie Windows i php> 5.5). :s
Stphane
$ foo = new MyAction; echo get_class ($ foo); Spowoduje to również wydrukowanie MyAction.
sammry
41

Od wersji 5.5 możesz używać classsłowa kluczowego do rozpoznawania nazw klas , co byłoby o wiele szybsze niż wywoływanie funkcji. Działa również z interfejsami.

// 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
źródło
16

Nie jest to idealne rozwiązanie, ale działa na PHP <5.3.0.

Kod został skopiowany z 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();
    }
}
Jrgns
źródło
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
źródło
0

W dostępnych wersjach PHP nie ma możliwości robienia tego, co chcesz. Rozwiązanie Paula Dixona jest jedyne. Mam na myśli przykład kodu, ponieważ funkcja późnych wiązań statycznych, o której mówi, jest dostępna od PHP 5.3, które jest w wersji beta.

Ionuț G. Stan
źródło
0

(PHP 5> = 5.3.0, PHP 7)
get_called_class - Nazwa klasy „Późne wiązanie statyczne”

<?php

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

class User extends Model
{
}


echo User::find();

ten link może być pomocny

Biswajit Biswas
źródło