【问题标题】:php reflection get properties without getting properties of base classphp反射获取属性而不获取基类的属性
【发布时间】:2013-01-16 05:11:43
【问题描述】:

所以我正在使用一个设置类,它扩展了一个类似于“全局设置”的基本设置类。有几个服务,每个服务都有自己的设置类,扩展了抽象的基本设置类。抽象基本设置类对应于服务之间共享的设置。所以首先我会用下面的例子来说明,然后我会定义问题:

示例:

abstract class BaseSettings {
    protected $settingA;
    protected $settingB;
}

class MyServiceSettings extends BaseSettings {
    private $settingC;
    public $settingD;
}

问题:

如果我像这样创建一个 ReflectionClass 实例..

$reflect = new ReflectionClass($this);

..来自 MyServiceSettings 类或 BaseSettings 类(因为显然你不能拥有抽象类的实例),$reflect->getProperties() 将始终返回 MyServiceSettings 和 BaseSettings 的属性(我猜这是合适的因为我们实际上是在使用一个具体的类)

现在我确信我可以创建一个空类来扩展抽象 BaseClass 以确定哪些属性去哪里(或者只是摆脱抽象并创建 BaseClass 的实例),但这看起来相当混乱,所以我我想知道是否有更优雅的方法来确定哪些属性属于父类,哪些属于子类?

如果您好奇我为什么要这样做 - 我正在将设置序列化为 .json 文件,以实现我添加的恢复功能,以便人们可以从最后一次成功完成的原子操作继续。为什么我必须这样做——环境的限制。

【问题讨论】:

    标签: php reflection


    【解决方案1】:

    我会这样理解:

    $class = new ReflectionClass('Some_class_name');
    $properties = array_filter($class->getProperties(), function($prop) use($class){ 
        return $prop->getDeclaringClass()->getName() == $class->getName();
    });
    

    所以基本上获取所有属性并遍历它们,检查它们是否在我们反映的类中声明。

    【讨论】:

      【解决方案2】:

      虽然上述方法仅用于获取 MyServiceSettings 的设置,但当您从 BaseSettings 类调用此方法时,它仍会返回扩展它的类的属性(只要您正在处理BaseSettings 类的实例,其中 BaseSettings 类已被另一个类扩展 - 无论 BaseSettings 类是抽象的还是具体的)至少当您在基类中将基类称为 $this 时类。

      也许有更好的解决方法,但我发现的只是简单地使用

      $reflectionClass = new ReflectionClass(get_parent_class($this));
      

      只是为了说明如何使用它,这里是我用来反序列化类及其基类的函数的改编:

      // "attribute" to be used in doc comments if it should not be
      // serialized / deserialized
      // ( remember: /** ... */ doc comments must have two asterisks!! )
      private $DoNotSerialize = "[@DoNotSerialize]";
      
      protected function dehydrate(ReflectionClass $reflectionClass) {
      
          // if you're using private or protected properties and need to use 
          // $property->setAccessible()
          if(floatval(phpversion()) < 5.3) {
              throw new Exception("requires PHP version 5.3 or greater");
          }
      
          clearstatcache();
      
          $properties = array_filter(
              $reflectionClass->getProperties(ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PUBLIC)
              , function($prop) 
                  use($reflectionClass) {
                      return $prop->getDeclaringClass()->getName() == $reflectionClass->getName();
                }
           );
      
          $settings = null;
      
          foreach($properties as $property) {
      
              $comment = $property->getDocComment();
              if( strpos($comment,$this->DoNotSerialize) !== false ){
                  continue;
              }
      
              if($property->isProtected()){
                  $property->setAccessible(TRUE);
              }
      
              if(isset($settings)) {
                  // implementation of array_push_associative
                  // can be found at http://php.net/manual/en/function.array-push.php
                  array_push_associative(
                      $settings
                      , array($property->getName() => $property->getValue($this))
                  );
              }
              else {
                  $settings = array($property->getName() => $property->getValue($this));
              }
          }
      
          //implementation irrelevant here
          writeToFile($reflectionClass->getName(), $settings);
      
          if(get_parent_class($reflectionClass)) {
              $this->dehydrate(get_parent_class($reflectionClass));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-05
        • 1970-01-01
        • 2011-02-15
        • 1970-01-01
        • 2017-05-14
        • 2011-10-02
        • 1970-01-01
        相关资源
        最近更新 更多