限制getter和setter可访问属性

时间:2018-06-15 14:04:31

标签: php class overloading visibility getter-setter

如何使用PHP的神奇__get()__set()方法并限制支持哪些属性?

我通常看到PHP的魔术方法用于重载以下两种方式,而且都不这样做。

我知道我可以对某些逻辑进行硬编码,但这样做并不能使这些类非常可扩展。

$obj1=new Entity1(new Foo, new Bar);
$obj1->propAccessible1='propAccessible1';           //Valid
var_dump($obj1->propAccessible1);                   //Valid
$obj1->privateObject1='privateObject1';             //Should not be allowed
var_dump($obj1->privateObject1);                    //Should not be allowed
$obj1->unsupportedProperty='unsupportedProperty';   //Correctly is not allowed
var_dump($obj1->unsupportedProperty);               //Correctly is not allowed

$obj2=new Entity2(new Foo, new Bar);
$obj2->propAccessible1='propAccessible1';           //Valid
var_dump($obj2->propAccessible1);                   //Valid
$obj2->privateObject1='privateObject1';             //Should not be allowed
var_dump($obj2->privateObject1);                    //Should not be allowed (will be if first set using setter)
$obj2->unsupportedProperty='unsupportedProperty';   //Should not be allowed
var_dump($obj2->unsupportedProperty);               //Should not be allowed

class Foo{}
class Bar{}

class Entity1
{
    private $privateObject1, $privateObject2;
    private $propAccessible1, $propAccessible2;

    public function __construct($injectedObject1, $injectedObject2) {
        $this->privateObject1=$injectedObject1;
        $this->privateObject2=$injectedObject2;
    }

    public function __get($property) {
        if (property_exists($this, $property)) return $this->$property;
        else throw new \Exception("Property '$property' does not exist");
    }

    public function __set($property, $value) {
        if (!property_exists($this, $property)) throw new \Exception("Property '$property' is not allowed");
        $this->$property = $value;
        return $this;
    }
}

class Entity2
{
    private $privateObject1, $privateObject2;
    private $data=[];

    public function __construct($injectedObject1, $injectedObject2) {
        $this->privateObject1=$injectedObject1;
        $this->privateObject2=$injectedObject2;
    }

    public function __set($property, $value) {
        $this->data[$property] = $value;
    }

    public function __get($property) {
        if (array_key_exists($property, $this->data)) {
            return $this->data[$property];
        }
        else throw new \Exception("Property '$property' does not exist");
    }
}

1 个答案:

答案 0 :(得分:1)

您可以稍微修改第二种方法。在$data中定义您的可访问密钥,并检查__set()中是否存在这些密钥,就像您在__get()中所做的一样。

class Entity2
{
    private $privateObject1, $privateObject2;
    private $data = [
        'accessible1' => null,
        'accessible2' => null
    ];

    public function __construct($injectedObject1, $injectedObject2)
    {
        $this->privateObject1 = $injectedObject1;
        $this->privateObject2 = $injectedObject2;
    }

    public function __set($property, $value)
    {
        if (array_key_exists($property, $this->data)) {
            $this->data[$property] = $value;
        } else throw new \Exception("Property '$property' does not exist");
    }

    public function __get($property)
    {
        if (array_key_exists($property, $this->data)) {
            return $this->data[$property];
        } else throw new \Exception("Property '$property' does not exist");
    }
}

我并不是真的相信严格避免PHP中的公共属性。如果他们无论如何都会通过魔术方法公开访问,我宁愿将它们声明为公开,以便更清楚地说明该课程是如何工作的。