带有私有属性的PHP序列化&吸气剂和制定者

时间:2018-02-06 14:47:09

标签: php getter-setter private-members json-serialization

我有一个基类,它使用php魔术方法__get和__set来修改扩展类中的私有属性。然后我为相关的私有属性构建了setter getter函数 (类似于这里发现的 http://www.beaconfire-red.com/epic-stuff/better-getters-and-setters-php

所以我的孩子课看起来如下:

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”),但它不会获取私有属性(即“ _状态”) 这是序列化函数:

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

            $json[$key] = $value;

    }
    return $json;
}

基类中的上述方法是否有任何方法可以识别子类中的所有Getter,以便它们可以包含在序列化中? 换句话说,我希望序列化包括“id”和“status”

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

3 个答案:

答案 0 :(得分:0)

使用ReflectionReflectionProperty::setAccessible

    public function jsonSerialize()
    {
        $json = array();
        $class = new ReflectionClass($this);
        foreach ($class->getProperties() as $key => $value) {
            $value->setAccessible(true);
            $json[$value->getName()] = $value->getValue($this);

        }
        return $json;
    }

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

答案 1 :(得分:0)

我采用不同的方法...我认为我更倾向于反思。 但我很想知道其他人是否同意。

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

这是我在基类中注册(存储getter / setter名称),将其存储在名为_getters的数组中。

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;
}

这种方法有什么问题吗?

答案 2 :(得分:0)

也许有些不同:

 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;
    }

您也可以序列化而不是返回数组。这种方法在子类上使用公共获取方法。