首页 文章

从PHP中使用动态类名获取静态属性

提问于
浏览
48

我有这个:

  • 一个包含类名的字符串变量( $classname

  • 一个包含属性名称的字符串变量( $propertyname

我想从该类中获取该属性,问题是,属性是静态的,我不知道该怎么做 .

如果属性不是静态的,那将是:

$classname->$propertyname;

如果属性是一个方法,我可以使用call_user_function

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

但就我而言,我只是输了 . 但我希望这是可能的 . 有了PHP拥有的数千个函数,他最好还有一些东西 . 也许我错过了什么?

谢谢!

编辑:

  • 对于那些有eval()解决方案的人:谢谢,但这是不可能的

  • 对于那些有get _class _vars()解决方案的人:谢谢,但似乎它返回 "the default properties of the given class" (php.net),是的,我希望这个值可以改变(即使它确实在某些情况下帮助我)

11 回答

  • -1

    如果您使用的是PHP 5.3.0或更高版本,则可以使用以下命令:

    $classname::$$propertyname;
    

    不幸的是,如果您使用的是低于5.3.0的版本,则使用eval()会遇到困难(如果值是动态的,则get_class_vars()将无效) .
    $ value = eval($ classname . ':: $' . $ propertyname . ';');


    EDIT: 我刚才说get_class_vars()如果值是动态的话就行不通,但显然,变量静态成员是"the default properties of a class"的一部分 . 您可以使用以下包装器:

    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() 使用此验证 should 是安全的 . 如果人们开始将随机内容设置为 $className$property ,它将退出该函数,因为它不是现有的类或属性 . 从 $value 开始,它实际上从未被解析为代码,因此无论它们放在哪里都不会影响脚本 .

  • 0

    我认为这是最简单的:

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

    要返回由静态变量设置的变量值,您需要调用:

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

    查看文档:: PHP Constant Documentation

  • 1

    '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' .

  • 0

    我注意到的一件事是你不能设置在静态类中受保护的变量,因为eval()命令在类外的范围内运行 . 解决这个问题的唯一方法是在每个运行eval()的类中实现一个静态方法 . 可以保护此方法,因为call_user_func()[调用setter方法]也从类内部运行 .

  • 74

    你应该可以这样做:

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

    我刚做了一个快速测试,并让它为我工作 . 不确定是否有更好的方法,但我找不到 .

  • 1

    潜在相关:关于PHP中后期静态绑定的讨论 - When would you need to use late static binding? .

  • 15

    get_class_varsget_object_vars 不同 .

    我认为 get_clas_vars 应该返回原始属性值 .

  • 0

    即使你说 eval 是不可能的,在PHP 5.3之前,最简单的解决方案仍然是使用 eval

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

    您可以使用ReflectionClass:

    class foo
    {
        private static $bar = "something";
    }
    
    $class = "foo";
    $reflector = new ReflectionClass($class);
    $static_vars = $reflector->getStaticProperties();
    var_dump($static_vars["bar"]);
    
  • 0

    在不使用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;
        }
    }
    

相关问题