Uzyskiwanie właściwości statycznych z klasy o dynamicznej nazwie klasy w PHP

Mam to:

  • jedna zmienna łańcuchowa, która przechowuje nazwę klasy ($classname)
  • jedna zmienna łańcuchowa z nazwą właściwości ($propertyname)

Chcę dostać tę właściwość z tej klasy, problem w tym, że właściwość jest statyczna i nie wiem jak to zrobić.

Gdyby nieruchomość nie była statyczna, to byłoby:

$classname->$propertyname;

Gdyby właściwość była metodą, mógłbym użyć call_user_function

call_user_func(array($classname, $propertyname));
Ale w moim przypadku, jestem po prostu zagubiony. Jestem jednak mając nadzieję, że jest to możliwe. Z tysiącami funkcji, które posiada PHP, lepiej, żeby miał coś do tego. Może coś przeoczyłem? Dzięki!

Edit:

  • dla osób z rozwiązaniami eval () : Dzięki, ale to nie wchodzi w grę
  • dla tych z get _class _vars () solutions: thanks, but it seems it returns "the default properties of the given class" (php.net), i tak, chciałbym, aby ta wartość była zmienny (mimo, że pomaga mi w niektórych przypadkach)
Author: Gabriel Moretti, 2009-08-14

11 answers

Jeśli używasz PHP w wersji 5.3.0 lub nowszej, możesz użyć:

$classname::$$propertyname;

Niestety, jeśli używasz wersji niższej niż 5.3.0, utknąłeś przy użyciu eval() (get_class_vars() nie będzie działać, jeśli wartość jest dynamiczna).

$value = eval($classname.'::$'.$propertyname.';');


EDIT: właśnie powiedziałem get_class_vars() nie działa, jeśli wartość jest dynamiczna, ale widocznie statyczne pręty zmiennych są częścią "domyślnych właściwości klasy" . Możesz użyć następującego wrappera:

function get_user_prop($className, $property) {
  if(!class_exists($className)) return null;
  if(!property_exists($className, $property)) return null;

  $vars = get_class_vars($className);
  return $vars[$property];
}

class Foo { static $bar = 'Fizz'; }

echo get_user_prop('Foo', 'bar'); // echoes Fizz
Foo::$bar = 'Buzz';
echo get_user_prop('Foo', 'bar'); // echoes Buzz

Niestety, jeśli chcesz ustawić wartość zmiennej, nadal będziesz musiał użyć eval(), ale z pewną walidacją w miejscu, to nie jest tak złe .

function set_user_prop($className, $property,$value) {
  if(!class_exists($className)) return false;
  if(!property_exists($className, $property)) return false;

  /* Since I cannot trust the value of $value
   * I am putting it in single quotes (I don't
   * want its value to be evaled. Now it will
   * just be parsed as a variable reference).
   */
  eval($className.'::$'.$property.'=$value;');
  return true;
}

class Foo { static $bar = 'Fizz'; }

echo get_user_prop('Foo', 'bar'); // echoes Fizz
set_user_prop('Foo', 'bar', 'Buzz');
echo get_user_prop('Foo', 'bar'); // echoes Buzz

set_user_prop() z tą walidacją powinno być bezpieczne. Jeśli ludzie zaczną umieszczać losowe rzeczy jako $className i $property, zakończy się to z funkcji, ponieważ nie będzie to istniejąca klasa lub właściwość. Od $value, nigdy nie jest faktycznie parsowany jako kod tak cokolwiek tam wrzucą, nie wpłynie na scenariusz.

 70
Author: Andrew Moore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 18:15:18

Myślę, że to najprostsze:

$foo = new ReflectionProperty('myClassName', 'myPropertyName'); 
print $foo->getValue();
 13
Author: Bahadır,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 12:12:03

Aby zwrócić wartość zmiennej ustawioną przez zmienną statyczną należy wywołać:

$static_value = constant($classname.'::'.$propertyname);

Sprawdź dokumentację:: PHP stała dokumentacja

 9
Author: frodosghost,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-27 05:31:02

'eval' wygląda tak blisko 'zła', i nienawidzę go używać i / lub widzieć w kodzie. Z kilkoma pomysłami z innych odpowiedzi, oto sposób, aby go uniknąć, nawet jeśli twój php nie jest 5.3 lub wyższy.

Zmieniono, aby odzwierciedlić testy na podstawie komentarza.

class A {
    static $foo = 'bar';
}

A::$foo = 'baz';
$a = new A;

$class = get_class($a);
$vars = get_class_vars($class);

echo $vars['foo'];

Wyjścia "baz".

 1
Author: nilamo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 17:43:05

Jedną rzeczą, którą zauważyłem jest to, że nie można ustawić zmiennych, które są chronione w klasach statycznych, ponieważ polecenie eval() działa w zakresie poza klasą. Jedyną rzeczą do obejścia tego byłoby zaimplementowanie statycznej metody wewnątrz klasy / every, która uruchamia EVAL (). Ta metoda może być chroniona, ponieważ call_user_func () [aby wywołać metodę setter] działa również z wewnątrz klasy.

 1
Author: mbirth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-01 17:38:11

Powinieneś być w stanie zrobić coś takiego:

eval("echo $classname::$propertyname;");
Zrobiłem szybki test i to mi się udało. Nie wiem, czy jest lepszy sposób, ale nie mogłem go znaleźć.
 0
Author: Steven Surowiec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-14 17:29:35

Potencjalnie istotne: dyskusja na temat późnego wiązania statycznego w PHP - Kiedy należy użyć późnego wiązania statycznego?.

 0
Author: Alex Weinstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:00:17

get_class_vars to nie to samo co get_object_vars.

Myślę, że get_clas_vars powinien zwrócić oryginalne wartości właściwości.

 0
Author: firzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-09 19:25:39

Nawet jeśli dla Ciebie {[1] } nie wchodzi w grę, wcześniejsze PHP 5.3 najprostszym rozwiązaniem jest użycie eval:

eval("\$propertyval = $classname::\$propertyname;");
echo $propertyval;
 0
Author: Marco Demaio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-23 20:37:16

Możesz użyć ReflectionClass:

class foo
{
    private static $bar = "something";
}

$class = "foo";
$reflector = new ReflectionClass($class);
$static_vars = $reflector->getStaticProperties();
var_dump($static_vars["bar"]);
 0
Author: Garlou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-09 14:00:29

Uzyskiwanie i ustawianie właściwości statycznych i niestatycznych bez użycia odbicia

Używanie odbicia działa, ale jest kosztowne

Oto, co używam do tego celu,

Działa na PHP 5 >= 5.1.0 ponieważ używam property_exist

function getObjectProperty($object, $property)
{
    if (property_exists(get_class($object), $property)) {
        return array_key_exists($property, get_object_vars($object))
            ? $object->{$property}
            : $object::$$property;
    }
}

function setObjectProperty($object, $property, $value)
{
    if (property_exists(get_class($object), $property)) {
        array_key_exists($property, get_object_vars($object))
            ? $object->{$property} = $value
            : $object::$$property = $value;
    }
}
 -1
Author: Arul Kumaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-24 04:18:08