2

这个问题与:PHP魔术方法示例有关

我在接受的答案中的评论中问了这个问题,但我想,它没有被注意到,所以我必须创建这个问题。

<?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;似乎创建了已定义为受保护的同名公共变量。那可能吗?

另外,在这个语句之后:$m->c = "CC";,当我们$m->c再次访问时,PHP__get再次调用,就好像c没有公共可见性一样。这是否意味着$this->$var = $val;没有生命周期来立即下一个声明?(我想也不会是这样)

谁能解释一下,它应该在这种情况下表现以及它是如何给出这样的输出的?

4

2 回答 2

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

第一次调用确实将属性设置bD,但是因为 getter 被硬编码为 return C,所以protected仍然尊重访问修饰符。

编辑。

魔术 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
)

它们只是函数,因此遵循相同的规则,唯一的区别是调用它们的方法。

于 2014-01-21T09:08:26.757 回答
1

您的 getter 和 setter 分别适用于不同的变量。

getter 访问属性 $b 的元素 setter 直接访问指定的属性。

可见性在这里无关紧要,因为您的所有访问都来自类的方法。因此,他们能够毫无区别地访问公共和受保护的属性。

将魔术函数想象成一个具有奇怪名称的普通函数。这与以这种方式访问​​它们相同:

$m->__get("a");
$m->__set("c", "CC");
于 2014-01-21T09:34:40.810 回答