我看起来很好看,似乎找不到这个问题的答案。
基本上我使用_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 :(得分: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]);
}
}
答案 1 :(得分: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 :(得分:2)
无论如何要将类中的变量声明为受保护的吗?
似乎不是这样。您可以Reflection使用change the accessibility of properties,但似乎这只能用于公开之前未公开的内容。
您可能希望考虑将自动生成的属性存储在具有适当可见性的数组中。
(还有__get
和__set
,但它们可能不符合您的需求。只有当属性缺失或无法访问时才会调用它们。能够触及受保护的属性会绕过它们。)