【问题标题】:PHP variable visibility and behaviour with magic method使用魔术方法的 PHP 变量可见性和行为
【发布时间】:2014-01-21 18:04:32
【问题描述】:

此问题与: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-&gt;c = "CC"; 这里我们已经有了同名的受保护变量。 那么,这在可见性的上下文中应该如何表现呢?

如果它覆盖了受保护变量c 的值,那么这不是受保护/私有变量的漏洞吗? (我想不会是这样)

如果不是,那么语句:$this-&gt;$var = $val; 似乎创建了已定义为受保护的同名公共变量。 这可能吗?

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

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

【问题讨论】:

  • 相关文章:All properties should be private!!;通读谷歌翻译。
  • 通常,魔术方法的全部意义在于暴露受保护的变量,并可能在途中使用一些逻辑。对于任何普通的公共变量,您都不需要它们。所以,是的,它正在按预期工作!如果您不想公开它们,请不要使用魔术方法或在这些方法中实现自己的过滤器。

标签: php visibility magic-methods zend-certification


【解决方案1】:

看起来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 被硬编码为返回Cprotected 访问修饰符仍然受到尊重。

编辑。

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

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

【讨论】:

  • public function __get($v) { return $this-&gt;$v; } 这会返回什么?
  • 它将返回您要求的任何属性的值(如果存在)。这是因为__get 方法属于该类,因此可以访问所有受保护的属性。
  • @CoolZeroInfinity 更新了答案,希望它能更清楚地说明这些方法是什么。
【解决方案2】:

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

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

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

把一个魔法函数想象成一个名字很奇怪的普通函数。和这样访问它们是一样的:

$m->__get("a");
$m->__set("c", "CC");

【讨论】:

  • 啊!是的,我的错 :-( 在这个例子中,没有可见性问题。
猜你喜欢
  • 2012-04-05
  • 2014-10-28
  • 1970-01-01
  • 2011-06-10
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
相关资源
最近更新 更多