从PHP中使用dynamic类名获得静态属性
我有这个:
- 一个保存类名的stringvariables(
$classname
) - 一个stringvariables与持有属性名称(
$propertyname
)
我想从那个类中获得这个属性,问题是,属性是静态的,我不知道该怎么做。
如果财产不是静态的,那将是:
$classname->$propertyname;
如果该属性是一种方法,我可以使用call_user_function
call_user_func(array($classname, $propertyname));
但就我而言,我刚刚输了。 然而,我希望这是可能的。 有了PHP的数以千计的function,他最好也有这个function。 也许我错过了什么?
谢谢!
编辑:
- 对于那些与eval()解决scheme:谢谢,但它是不可能的
- 对于那些获得_class _vars()解决scheme:谢谢,但它似乎返回“给定类的默认属性” (php.net),是的,我希望这个值是可变的(即使它帮助我在某些情况下)
如果您使用PHP 5.3.0或更高版本,则可以使用以下内容:
$classname::$$propertyname;
不幸的是,如果您使用的是低于5.3.0的版本,那么您将使用 eval()
(如果值是dynamic的, get_class_vars()
将不起作用)。
$value = eval($classname.'::$'.$propertyname.';');
编辑:我只是说,如果该值是dynamic的get_class_vars()
将无法正常工作,但显然,variables静态成员是“类的默认属性”的一部分 。 你可以使用下面的包装器:
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
不幸的是,如果你想设置variables的值,你仍然需要使用eval()
,但是通过一些validation,这并不是那么邪恶 。
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
这个validation的set_user_prop()
应该是安全的。 如果人们开始把随机的东西当作$className
和$property
,它将退出函数,因为它不会是现有的类或属性。 从$value
,它永远不会被parsing为代码,因此不pipe它们放在哪里都不会影响脚本。
我认为这是最简单的:
$foo = new ReflectionProperty('myClassName', 'myPropertyName'); print $foo->getValue();
要返回由静态variables设置的variables值,您需要调用:
$static_value = constant($classname.'::'.$propertyname);
查阅文档:: PHP常量文档
我注意到的一件事是,你不能设置在静态类中被保护的variables,因为eval()命令在类的范围外运行。 解决这个问题的唯一方法是在运行eval()的每个类中实现一个静态方法。 这个方法可以被保护,因为调用setter方法的call_user_func()也是从类里面运行的。
你应该能够做到这样的事情:
eval("echo $classname::$propertyname;");
我只是做了一个快速testing,并得到这个为我工作。 不知道有没有更好的方法,但我没有find一个。
“eval”看起来如此接近“邪恶”,我讨厌使用它和/或在代码中看到它。 从其他答案的一些想法,这是一个避免它,即使你的PHP不是5.3或更高的方法。
更改为反映基于评论的testing。
class A { static $foo = 'bar'; } A::$foo = 'baz'; $a = new A; $class = get_class($a); $vars = get_class_vars($class); echo $vars['foo'];
输出'baz'。
潜在的相关:在PHP中后期静态绑定的讨论 – 你什么时候需要使用迟静态绑定? 。
get_class_vars
与get_object_vars
。
我认为get_clas_vars
应该返回原来的属性值。
即使对于你说的eval
是eval
的,以前的PHP 5.3最简单的解决scheme仍然是使用eval
:
eval("\$propertyval = $classname::\$propertyname;"); echo $propertyval;
您可以使用ReflectionClass:
class foo { private static $bar = "something"; } $class = "foo"; $reflector = new ReflectionClass($class); $static_vars = $reflector->getStaticProperties(); var_dump($static_vars["bar"]);
在不使用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; } }