此问题与:PHP magic methods example
有关我在接受的答案中已经在评论中提出这个问题,但我想,它没有被注意到所以我必须创建这个问题。
<?php
class Magic {
public $a = "A";
protected $b = array(
"a"=>"A",
"b"=>"B",
"c"=>"C"
);
protected $c = array(1,2,3);
public function __get($v) {
echo "$v,";
return $this->b[$v];
}
public function __set($var, $val) {
echo "$var: $val,";
$this->$var = $val;
}
}
$m = new Magic();
echo $m->a.",".$m->b.",".$m->c.",";
$m->c = "CC";
echo $m->a.",".$m->b.",".$m->c;
?>
输出:
b,c,A,B,C,c: CC,b,c,A,B,C
$m->c = "CC";
这里我们已经有了同名的受保护变量。
那么,这应该如何在可见性的背景下表现呢?
如果它覆盖了受保护变量c
的值,那么它不是受保护/私有变量的循环漏洞吗? (我猜不会是这种情况)
如果没有,语句:$this->$var = $val;
似乎创建了具有相同名称的公共变量,已经定义为protected。
这可能吗?
此后,在此声明之后:$m->c = "CC";
,当我们再次访问$m->c
时,PHP再次调用__get
,就像c
没有公开可见性一样。
这是否意味着$this->$var = $val;
没有终身下一次陈述的生命时间? (我想也不会这样)
任何人都可以解释一下,它应该在这种情况下表现出来以及它是如何产生这样的输出的吗?
答案 0 :(得分:2)
看起来c
仅通过方法进行更改。虽然它受到保护,但神奇的方法暴露了它。
如果你看一下这个例子:
class Magic
{
protected $b = 'B';
public function __get($v)
{
return 'C';
}
public function __set($v, $val)
{
$this->$v = $val;
}
}
$magic->b = 'D';
echo $magic->b; // Outputs: C
第一次调用会将属性b
设置为D
,但由于getter已经过硬编码以返回C
,因此仍然会尊重protected
访问修饰符。< / p>
EDIT。
魔术getter / setter的另一个用途是访问集合。这个例子展示了它们的灵活性:
class Magic
{
private $properties = array();
public function __get($key)
{
if(isset($this->properties[$key])) {
return $this->properties[$key];
}
}
public function __set($key, $value)
{
$this->properties[$key] = $value;
}
public function dump($return = false)
{
if($return) {
return print_r($this->properties, true);
} else {
print_r($this->properties);
}
}
}
$magic = new Magic();
$magic->a = '123';
$magic->b = '456';
$magic->c = '789';
echo '<pre>';
echo sprintf('A: %s%s', $magic->a, PHP_EOL);
echo sprintf('B: %s%s', $magic->b, PHP_EOL);
echo sprintf('C: %s%s', $magic->c, PHP_EOL);
echo PHP_EOL;
echo $magic->dump(true);
输出:
A: 123
B: 456
C: 789
Array
(
[a] => 123
[b] => 456
[c] => 789
)
它们只是函数,因此遵循相同的规则,唯一的区别是它们被调用的方法。
答案 1 :(得分:1)
你的getter和setter都适用于不同的变量。
getter访问属性$ b的元素 setter直接访问指定的属性。
可见性在这里无关紧要,因为您的所有访问都是从类的方法发生的。因此,他们能够毫无差别地访问公共和受保护的属性。
将魔术函数视为具有奇怪名称的普通函数。这与以这种方式访问它们相同:
$m->__get("a");
$m->__set("c", "CC");