Получение статического свойства из класса с динамическим именем класса в PHP
У меня есть это:
- одна строковая переменная, которая содержит имя класса (
$classname
)
- одна строковая переменная с именем свойства (
$propertyname
)
Я хочу получить это свойство из этого класса, проблема в том, что свойство является статическим, и я не знаю, как это сделать.
Если свойство не было статическим, это было бы:
$classname->$propertyname;
Если свойство было методом, я мог бы использовать функцию call_user_function
call_user_func(array($classname, $propertyname));
Но в моем случае я просто проиграл. Однако я надеюсь, что это возможно. С тысячами функций, которые имеет PHP, у него тоже есть что-то для этого. Может, я что-то упустил?
Спасибо!
Edit:
- для тех, у кого eval() решения: спасибо, но это не может быть и речи.
- для тех, у кого получить _class _vars() решения: спасибо, но кажется, что он возвращает "свойства по умолчанию данного класса" (php.net), и да, я хотел бы, чтобы это значение менялось (даже если оно помогает мне в некоторых случаях)
Ответы
Ответ 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".
Ответ 7
Потенциально актуально: обсуждение поздней статической привязки в PHP - Когда вам нужно использовать позднюю статическую привязку?.
Ответ 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;
}
}