【问题标题】:Restrict getter and setter accessible properties限制 getter 和 setter 可访问的属性
【发布时间】:2018-11-25 09:29:13
【问题描述】:

应该如何使用 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");
    }
}

【问题讨论】:

  • 什么是属性,请给我们一些属性的例子,如果你只想限制字符串或整数..等,我认为你可以使用类型声明,如果它是我认为的任何其他属性您需要在 setter 中对逻辑进行硬编码
  • @vSugumar 我主要关心的是不希望允许公开访问注入的对象。第二种方法实际上达到了这个目标,但是,它不限制支持的属性。以前,我使用过第一种方法,但是在完成这个练习之后,我认为第二种方法更好。是吗?
  • 如果我正确理解您要执行的操作,您似乎可以将可访问的属性公开可见,而根本不使用魔术方法。我一定是错过了什么。
  • 是的,在第二种方法中无法访问您注入的对象,但我仍然没有理解您的观点“它不限制支持的属性”请让我理解
  • @Don'tPanic 是的,我可以,但很多人会声称我不应该公开它们。

标签: php class overloading visibility getter-setter


【解决方案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 中的公共属性。如果它们无论如何都可以通过魔术方法公开访问,我宁愿将它们声明为公开的,以便更清楚地了解该类的工作原理。

【讨论】:

  • 谢谢不要恐慌。我想这是假设非公共属性并使用魔术方法的最佳选择。我还没有使用它们,但是可以使用 doc 标签来澄清。也许最好只制作单独的 getter 和 setter 而不是魔术方法?
  • 我宁愿做个人访问者。不过,只是我的看法。 :)
  • 并以getPropAccessible1()setPropAccessible1("hello") 的身份访问它们,对吗?
  • 是的,就像那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 1970-01-01
相关资源
最近更新 更多