带有私有属性的PHP序列化&;getters&;二传手

带有私有属性的PHP序列化&;getters&;二传手,php,getter-setter,private-members,json-serialization,Php,Getter Setter,Private Members,Json Serialization,我有一个基类,它使用php魔术方法_get和_set来修改扩展类中的私有属性。然后,我为相关的私有属性构建了setter-getter函数 (与此处发现的类似 ) 因此,我的儿童课程将如下所示: class User extends BaseObject { public $id = -1; private $_status = ""; function __construct($members = array()) { parent::__const

我有一个基类,它使用php魔术方法_get和_set来修改扩展类中的私有属性。然后,我为相关的私有属性构建了setter-getter函数 (与此处发现的类似 )

因此,我的儿童课程将如下所示:

class User extends BaseObject {
    public $id = -1;
    private $_status = "";


    function __construct($members = array()) {
        parent::__construct($members);

    }

    //Setter/Getter
    public function status($value = null) {
       if($value) {
           $this->_status = $value;

       } else {
           return $this->_status;
      }
}
现在,当我序列化基类中的JsonSerialize方法这个对象时,序列化只会从子类(即“Id”)中获取公共属性,但不会获取私有属性(即“u status”) 这是序列化函数:

 public function jsonSerialize() {
    $json = array();
    foreach($this as $key => $value) {

            $json[$key] = $value;

    }
    return $json;
}
基类中的上述方法是否有任何方法可以标识子类中的所有getter,以便它们可以包含在序列化中? 换句话说,我希望序列化同时包含“id”和“status”

我意识到我可以获取类上的所有方法,并使用某种命名约定来标识getter/setter,但我特别需要保持getter/setter名称与属性名称相同,即_status必须有一个名为status()的getter setter 那么,有没有其他方法来识别这些特定功能呢

使用和:


这是为了回答明确的问题。但我不确定您是否应该使用此设计来解决您的问题。

我将采用不同的方法…我认为我更喜欢它而不是反射。 但我很想听听其他人是否同意

我将根据访问的时间在子类中注册每个Getter/Setter,即将Getter/Setter名称存储在数组中。 在序列化时,我不仅要对所有公共属性进行交互,还要对已注册的getter/setter进行交互

这里是我在基类中注册(存储getter/setter名称)的时候,将它存储在一个名为_getter的数组中

function __set($name,$value){
    if(method_exists($this, $name)){
        $this->$name($value);
        //save in getters list for serialization
        if(!in_array($name,$this->_getters))
            array_push($this->_getters,$name);
    }
    else{
        // Getter/Setter not defined so set as property of object
        $this->$name = $value;
    }
}
现在在我的序列化中,我还检索所有注册的getter并序列化它们。 它工作得很好

    public function jsonSerialize() {
    $json = array();
    //do public properties

    foreach($this as $key => $value) {
            $json[$key] = $value;

    }

    //do any getter setters
    foreach($this->_getters as $key => $getter) {
        $value = $this->$getter;
        $json[$getter] = $value;

    }
    return $json;
}

这种方法有什么问题吗?

可能有点不同的方法:

 public function toArray()
    {
        $descriptor = new \ReflectionClass(get_class($this));
        /** @var \ReflectionMethod[] $methods */
        $methods = $descriptor->getMethods(\ReflectionMethod::IS_PUBLIC);
        $array   = [];
        foreach ($methods as $method) {
            if (substr_compare('get', $method->getName(), 0, 3) === 0) {
                $property         = lcfirst(substr($method->getName(), 3));
                $value            = $method->invoke($this);
                $array[$property] = $value;
            }
        }

        return $array;
    }

您还可以序列化它,而不是返回数组。这种方法在子类上使用公共getter方法。

请在stackoverflow.FWIW上阅读此内容,如果这是您的实际setter,您不应该使用它。它没有任何作用。只需将属性
公开
并分配给它即可。谢谢。这不是我真正的二传手。我的实际设置者正在设置一些其他属性。那么你有更好的解决方案吗?这肯定是在…序列化具有私有属性和getter/setter函数的对象之前完成的?最好的方法是什么?你有什么问题如果您想要一个对象表示,我将使用我需要的所有getter手动构建它。如果您不能修改基类,那么反射就是我修改基类的方式,因为我正在构建多个子类,这些子类都需要getter/setter序列化,所以我想将其放入基类中。我想我更喜欢getter/setter注册(我上面提到过)而不是反射
 public function toArray()
    {
        $descriptor = new \ReflectionClass(get_class($this));
        /** @var \ReflectionMethod[] $methods */
        $methods = $descriptor->getMethods(\ReflectionMethod::IS_PUBLIC);
        $array   = [];
        foreach ($methods as $method) {
            if (substr_compare('get', $method->getName(), 0, 3) === 0) {
                $property         = lcfirst(substr($method->getName(), 3));
                $value            = $method->invoke($this);
                $array[$property] = $value;
            }
        }

        return $array;
    }