2010-07-31 105 views
4

我已经很好看,并且似乎无法找到此问题的答案。在方法中声明受保护的变量

基本上我使用_call方法来动态生成get和set方法,但是当声明一个变量时PHP的默认值是public的。无论如何,从类内部声明一个变量为受保护的?

function __call($method, $arguments) { 
    $prefix = strtolower(substr($method, 0, 3)); 
    $property = strtolower(substr($method, 3)); 

    if (empty($prefix) || empty($property)) { 
     return; 
    } 

    if ($prefix == "get" && isset($this->$property)) { 
     return $this->$property; 
    } 

    if ($prefix == "set") { 

     $this->$property = $arguments[0]; 
    } 
} 
+0

出于兴趣,您为什么使用__call而不是__get和__set? – 2010-07-31 17:08:23

+0

只是似乎更容易,我也从这里复制它: http://onlamp.com/pub/a/php/2005/06/16/overloading.html – 2010-07-31 17:09:43

回答

6

一种选择是拥有一个受保护的数组,并从你的魔法设置器中设置该数组中的一个元素。

class MyClass { 
    protected $_myProperties = array(); 

    public function __get($name) { 
     if (isset($this->_myProperties[$name])) { 
      return $this->_myProperties[$name]; 
     } else { 
      return null; 
     } 
    } 

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

    public function __isset($name) { 
     return isset($this->_myProperties[$name]); 
    } 
} 
+0

谢谢,完成了这一步。完美的工作,但保持呼叫方法习惯使用$ class-> getSomething(); – 2010-07-31 17:33:23

2

反正是有作为保护从类中声明一个变量?

似乎并不如此。您可以使用Reflectionchange the accessibility of properties,但似乎只能有效地用于公开事先未公开的内容。

您可能希望考虑将自动生成的属性存储在具有正确可见性的数组中。

(还有__get__set,但他们可能不适合您的需求。他们会只被调用时,属性缺失无法访问。类是能够触摸保护的特性会绕过它们。)

+0

是的,我同意你的第二段... ...存储这些_generated_'属性'在关联数组中。关联数组然后可以是您的类的受保护属性。为了使用'__get'或'__set' _我想_你需要这样做。 – MrWhite 2010-07-31 17:18:35

+0

我不同意。这打破了成员变量的观点。当类将存储未知变量(如注册表类或类似的东西)时,我使用关联数组。但是当你有一组有限的已知变量时,为什么不使用成员变量来设计它们? – ircmaxell 2010-07-31 17:19:44

+0

我只能想象,从这个问题来看,他正在做某种古怪的继承和/或能见度魔术。除非上面的代码不完整,否则我不会看到对属性进行了任何转换... – Charles 2010-07-31 17:22:08

5

首先,我会强烈建议不要returning如果前缀或属性变量未设置。它会使调试非常困难。相反,将return;替换为throw new BadMethodCallException('Method Does Not Exist: '.$method);

其次,是不是破坏了保护变量的点?它允许读写所有属性而不需要任何验证。如果你打算这样做,你不妨将它们公诸于众。

我个人认为$foo->bar = 'baz';$foo->setBar('baz');更具可读性。不是因为它更容易理解,而是因为第二个是不必要的冗长。

就我个人而言,我会建议做一个__get__set,并添加验证。保护变量的重点在于信任(以便您可以信任这些设置)。当然,你可以使用反射或分类来改变它们,但我通常假设如果有人走得太远,如果他们弄乱了一个变量,他们应该有任何意想不到的结果。

而且记住,如果你使用任何类型的魔术方法的,你需要,如果你想你的IDE暗示的方法来添加文档元素/变量来你...

编辑:

别忘了,如果您声明__get/__set方法,您可以在子类中覆盖它们。所以如果孩子声明了新变量,你可以在那里处理它们,然后调用parent::__get来处理默认变量。所以,不要为了让所有的孩子都能拥有一个方法而使用数组。为你认识的成员做验证,并让你的孩子处理他们自己的验证...

+2

+1不同意$ foo-> setBar('baz');与$ foo-> bar ='baz'相比,是不必要的verbode;因为getter和setter方法总是允许设置属性的验证,而非私有属性总是可以绕过任何验证来设置......但是这里有很多非常有用的信息片段 – 2010-07-31 17:26:35

+0

这只是我可能使用的任何变量的回退方法需要添加到一个类。一般来说,我总是在受保护的变量需要时使用get和set方法。我完全理解调试的困难,只会谨慎地使用这种方法来实现DRY。 – 2010-07-31 17:26:52

+0

嗯,我不时使用'getBar()'语法,但我尽量不去尝试,除非它真的有意义。我只是不喜欢为了获取/设置成员变量而在课堂中使用50个方法的混乱状态......大多数情况下它不是必需的(但并非总是)... – ircmaxell 2010-07-31 17:34:28