【问题标题】:Can I get the value of a private property with Reflection?我可以通过反射获得私有财产的价值吗?
【发布时间】:2012-07-22 23:51:26
【问题描述】:

它似乎不起作用:

$ref = new ReflectionObject($obj);

if($ref->hasProperty('privateProperty')){
  print_r($ref->getProperty('privateProperty'));
}

进入IF循环,然后抛出错误:

属性 privateProperty 不存在

:|

$ref = new ReflectionProperty($obj, 'privateProperty') 也不起作用...

documentation page 列出了一些常量,包括IS_PRIVATE。如果我无法访问私有财产大声笑,我怎么能使用它?

【问题讨论】:

  • IS_PRIVATE 和其他常量适用于 getProperties(复数 - 不是 getProperty)方法

标签: php reflection


【解决方案1】:
class A
{
    private $b = 'c';
}

$obj = new A();

$r = new ReflectionObject($obj);
$p = $r->getProperty('b');
$p->setAccessible(true); // <--- you set the property to public before you read the value

var_dump($p->getValue($obj));

【讨论】:

  • 您的示例似乎有效,但我的无效:(可能是因为我的班级是子班吗?
  • @Alex:看看它们之间的区别。你肯定错过了什么
  • @Alex: 是的,private 仅对创建它们的类可见。但在这种情况下,hasProperty 将返回 false
  • 就是这样:s codepad.org/lx8ecZMz ..有什么办法可以获得子类属性吗?
  • 我知道这个问题已经很老了,但是我只是浪费了一些时间来寻找如何从孩子那里访问父母的私有财产价值并阅读这些不完整的答案的方法,我希望它会节省别人的时间:$p = $r-&gt;getParentClass()-&gt;getProperty('b');
【解决方案2】:

请注意,如果您需要获取来自父类的私有属性的值,则接受的答案将不起作用。

为此,您可以依赖getParentClass method of Reflection API

另外,this micro-library 已经解决了这个问题。

更多详情请见this blog post

【讨论】:

    【解决方案3】:

    getProperty 抛出异常,而不是错误。意义在于,你可以搞定,给自己留个if

    $ref = new ReflectionObject($obj);
    $propName = "myProperty";
    try {
      $prop = $ref->getProperty($propName);
    } catch (ReflectionException $ex) {
      echo "property $propName does not exist";
      //or echo the exception message: echo $ex->getMessage();
    }
    

    要获取所有私有属性,请使用$ref-&gt;getProperties(ReflectionProperty::IS_PRIVATE);

    【讨论】:

    • 请注意,IS_PRIVATE 应该是 ReflectionProperty::IS_PRIVATE
    【解决方案4】:

    如果您需要它没有反射:

    public function propertyReader(): Closure
    {
        return function &($object, $property) {
            $value = &Closure::bind(function &() use ($property) {
                return $this->$property;
            }, $object, $object)->__invoke();
             return $value;
        };
    }
    

    然后像这样使用它(在同一个类中):

    $object = new SomeObject();
    $reader = $this->propertyReader();
    $result = &$reader($object, 'some_property');
    

    【讨论】:

      【解决方案5】:

      不用反射,也可以做

      class SomeHelperClass {
          // Version 1
          public function getProperty1 (object $object, string $property) {
              return Closure::bind(
                  function () use ($property) {
                      return $this->$property;
                  },
                  $object,
                  $object
              )();
          }
      
          // Version 2
          public function getProperty2 (object $object, string $property) {
              return (
                  function () use ($property) {
                      return $this->$property;
                  }
              )->bindTo(
                  $object,
                  $object
              )->__invoke();
          }
      }
      

      然后是类似的东西

      SomeHelperClass::getProperty1($object, $propertyName)
      SomeHelperClass::getProperty2($object, $propertyName)
      

      应该可以。

      这是尼古拉·斯托吉尔科维奇的回答的简化版

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-17
        • 2012-03-02
        • 1970-01-01
        • 2012-03-12
        • 1970-01-01
        • 1970-01-01
        • 2020-11-25
        相关资源
        最近更新 更多