【问题标题】:PHP Accessing a child's private properties in parentPHP在父级中访问子级的私有属性
【发布时间】:2011-03-29 21:20:49
【问题描述】:

我有一个父对象,用于在我的应用程序中进行一般 CRUD - 它具有基本的保存和检索方法,因此我不必将它们重新包含在我的所有对象中。我的大多数子对象都扩展了这个基础对象。这工作正常,但我发现检索序列化子对象存在问题。我在创建子对象实例的父对象中使用“检索”方法,然后从未序列化子对象的属性中填充自身 - 这意味着可以“自我反序列化”对象。

唯一的问题是 - 如果子对象具有受保护或私有属性,则父对象无法读取它,因此在检索期间不会被拾取。

所以我正在寻找一种更好的“自我反序列化”方法,或者一种允许父对象“看到”受保护属性的方法 - 但仅限于检索过程中。

代码示例:

BaseObject {

 protected $someparentProperty;

 public function retrieve() {

  $serialized = file_get_contents(SOME_FILENAME);
  $temp = unserialize($serialized);
  foreach($temp as $propertyName => $propertyValue) {
    $this->$propertyName = $propertyValue;
  }     

 }

 public function save() {

    file_put_contents(SOME_FILENAME, serialize($this));
 }
}

class ChildObject extends BaseObject {

 private $unretrievableProperty;  

 public setProp($val) {
    $this->unretrivableProperty = $val;
 }
}

$tester = new ChildObject();
$tester->setProp("test");
$tester->save();

$cleanTester = new ChildObject();
$cleanTester->retrieve();
// $cleanTester->unretrievableProperty will not be set

已编辑:应该说“私人”不受保护的子属性。

【问题讨论】:

    标签: php oop serialization protected


    【解决方案1】:

    解决此问题的最佳方法是使用反射

    示例:

    $_SESSION[''] = ''; // init
    
    class Base {
        public function set_proxy(){
            $reflectionClass = new ReflectionClass($this);
            $ar = $reflectionClass->getDefaultProperties();
    
            !isset($ar['host'])  or  $_SESSION['host'] = $ar['host'];
        }
    }
    
    class Son1 extends Base {
        private $host = '2.2.2.2';
    }
    
    class Son2 extends Son1 {
    
    }
    
    
    $son1 = new Son1();
    $son1->set_proxy(); 
    var_dump($_SESSION); // array(2) { [""]=> string(0) "" ["host"]=> string(7) "2.2.2.2" }
    
    unset($_SESSION);
    $_SESSION[''] = ''; // init
    
    $son2 = new Son2();
    $son2->set_proxy(); 
    var_dump($_SESSION); //  array(1) { [""]=> string(0) "" }
    

    【讨论】:

      【解决方案2】:

      试试这样:

      abstract class ParentClass
      {
        protected abstract function GetChildProperty();
      
        public function main()
        {
          $value = $this->GetChildProperty();
        }
      }
      
      class ChildClass extends ParentClass
      {
        private $priv_prop = "somevalue";
      
        protected function GetChildProperty()
        {
          return $this->priv_prop;
        }
      }
      

      【讨论】:

        【解决方案3】:

        似乎同一类可见性策略不适用于继承/父类。 php 文档没有解决这个问题。

        我建议您将检索方法声明为静态,并通过静态调用而不是您当前的“自我反序列化”方法获取 $cleanTester。

        static function retrieve() {
          $serialized = file_get_contents(SOME_FILENAME);
          return unserialize($serialized);
        }
        
        [...]
        
        $cleanTester = BaseObject::retrieve();
        

        或者您可以利用__get() 方法访问不可访问的属性...我相信这可以添加到BaseObject 类并从子类中获取受保护的属性。由于相同的类可见性策略应适用于 BaseObject,因此您可以定义 __get() 方法 private 或 protected。

        BaseObject {
          private function __get($propertyName) {
            if(property_exists($this,$propertyName))
              return $this->{$propertyName};
        
            return null;
          }
        

        【讨论】:

        • 谢谢。静态方法似乎是可行的——但事实上,一些子对象需要被实例化,并在它们可以计算出应该从中检索的文件名之前进行一些处理。 __get 已经被使用了,几乎就是为了这个目的——但是当我遍历对象的属性时,父级再次不知道要请求什么属性。我想我需要看看迭代方法 - 感谢指针。
        【解决方案4】:

        子对象中的 getProperty() 函数如何返回 $this->unretrievableProperty

        【讨论】:

        • 谢谢 - 好主意,但由于 baseobject 不知道孩子的属性,它不知道要求什么
        猜你喜欢
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 1970-01-01
        • 2011-09-26
        • 2011-11-06
        • 1970-01-01
        • 2021-10-31
        • 2017-06-09
        相关资源
        最近更新 更多