Подтвердить что ты не робот

Получение статического свойства из класса с динамическим именем класса в PHP

У меня есть это:

  • одна строковая переменная, которая содержит имя класса ($classname)
  • одна строковая переменная с именем свойства ($propertyname)

Я хочу получить это свойство из этого класса, проблема в том, что свойство является статическим, и я не знаю, как это сделать.

Если свойство не было статическим, это было бы:

$classname->$propertyname;

Если свойство было методом, я мог бы использовать функцию call_user_function

call_user_func(array($classname, $propertyname));

Но в моем случае я просто проиграл. Однако я надеюсь, что это возможно. С тысячами функций, которые имеет PHP, у него тоже есть что-то для этого. Может, я что-то упустил?

Спасибо!

Edit:

  • для тех, у кого eval() решения: спасибо, но это не может быть и речи.
  • для тех, у кого получить _class _vars() решения: спасибо, но кажется, что он возвращает "свойства по умолчанию данного класса" (php.net), и да, я хотел бы, чтобы это значение менялось (даже если оно помогает мне в некоторых случаях)
4b9b3361

Ответ 1

Если вы используете PHP 5.3.0 или новее, вы можете использовать следующее:

$classname::$$propertyname;

К сожалению, если вы используете версию ниже 5.3.0, вы застреваете с помощью eval() (get_class_vars() не будет работать, если значение является динамическим).

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

Забастовкa >


EDIT: Я только что сказал get_class_vars() не будет работать, если это значение является динамическим, но по-видимому, переменные статические члены являются частью "свойств по умолчанию для класса". Вы можете использовать следующую оболочку:

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

К сожалению, если вы хотите установить значение переменной, вам все равно придется использовать eval(), но с некоторой проверкой в место, это не так злобно.

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(), при этом проверка должна быть безопасной. Если люди начинают ставить случайные вещи как $className и $property, они выйдут из функции, поскольку это не будет существующий класс или свойство. Начиная с $value, он никогда не анализируется как код, поэтому все, что они там помещают, не повлияет на script.

Ответ 2

Я думаю, что это самое простое:

$foo = new ReflectionProperty('myClassName', 'myPropertyName'); 
print $foo->getValue();

Ответ 3

Чтобы вернуть значение переменной, заданное переменной Static, вам необходимо вызвать:

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

Посмотрите документацию:: Постоянная документация PHP

Ответ 4

Одна вещь, которую я заметил, это то, что вы не можете устанавливать переменные, которые защищены в статических классах, поскольку команда eval() запускается в области вне класса. Единственное, что можно обойти, это реализовать статический метод внутри/каждого класса, который запускает eval(). Этот метод может быть защищен, так как call_user_func() [для вызова метода setter] также запускается изнутри класса.

Ответ 5

Вы должны иметь возможность сделать что-то вроде:

eval("echo $classname::$propertyname;");

Я только что сделал быстрый тест и заставил это работать для меня. Не уверен, есть ли лучший способ или нет, но я не смог его найти.

Ответ 6

'eval' выглядит так близко к "злу", и я ненавижу использовать его и/или видеть его в коде. Имея несколько идей из других ответов, здесь можно избежать этого, даже если ваш php не равен 5.3 или выше.

Изменено для отражения тестирования на основе комментария.

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

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

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

echo $vars['foo'];

Выводит "baz".

Ответ 8

get_class_vars не совпадает с get_object_vars.

Я думаю, что get_clas_vars должен возвращать исходные значения свойств.

Ответ 9

Даже если вы сказали, что eval не может быть и речи, предшествующий PHP 5.3, самое легкое решение по-прежнему использует eval:

eval("\$propertyval = $classname::\$propertyname;");
echo $propertyval;

Ответ 10

Вы можете использовать ReflectionClass:

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

$class = "foo";
$reflector = new ReflectionClass($class);
$static_vars = $reflector->getStaticProperties();
var_dump($static_vars["bar"]);

Ответ 11

Получение и установка статических и нестатических свойств без использования Reflection

Использование Reflection работает, но это дорогостоящий

Вот что я использую для этой цели,

Он работает для PHP 5 >= 5.1.0, потому что я использую 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;
    }
}