使用__get,__ set和__unset在类中出现意外的数组内容

时间:2010-06-23 14:22:39

标签: php arrays overloading unset

我已经创建了一个我正在解决的问题的简短演示。这并不是我实现它的方式,但似乎导致了同样的结果。

<?php

class mainclass {

    var $vardata = array();

    function &__get ($var) {
        if ($this->vardata[$var]) return $this->vardata[$var];
        if ($var == 'foo') return $this->_loadFoo();
        return NULL;
    }

    function __set ($var, $val) {
        $this->vardata[$var] = $val;
    }

    function __unset($var) {
        unset($this->vardata[$var]);
    }

}

class extender extends mainclass {

    function __construct() {

        var_dump($this->foo);
        $this->_loadFoo();
        echo '<br>';
        var_dump($this->foo);

    }

    function _loadFoo () {

        unset($this->foo);
        $this->foo = array();

        $this->foo[] = 'apples';
        $this->foo[] = 'oranges';
        $this->foo[] = 'pears';

        return $this->foo;

    }

}


$test = new extender;

?>

上述代码的输出是:

array(3) { [0]=>  string(6) "apples" [1]=>  string(7) "oranges" [2]=>  string(5) "pears" }
array(5) { [0]=> string(6) "apples" [1]=> string(7) "oranges" [2]=> string(5) "pears" [3]=> string(7) "oranges" [4]=> string(5) "pears" } 

我期待的地方:

array(3) { [0]=>  string(6) "apples" [1]=>  string(7) "oranges" [2]=>  string(5) "pears" }
array(3) { [0]=>  string(6) "apples" [1]=>  string(7) "oranges" [2]=>  string(5) "pears" }

__ get,__ set和__unset函数都在正确的位置被调用,所以我希望第二次直接调用函数来简单地取消设置$ this-&gt; foo并用相同的数据再次填充它。这意味着var_dumping它将提供相同的输出。相反,好吧,它最终完成上述操作...用直接设置的三个字符串中的两个填充它并保持前三个最初设置的字符串。

也许只是一个愚蠢的错误或对重载函数的误解 - 无论哪种方式,我已经被困在这里太久了所以任何帮助都非常感激!

1 个答案:

答案 0 :(得分:0)

您的代码存在许多问题:

  • if ($this->vardata[$var])不是检查变量存在的方法; isset或(如果允许空值,array_key_exists)是。
  • mainclass调用了它没有的功能。你应该已经将它声明为抽象(否则它仍会起作用,但如果你实例化了mainclass,你就会暴露自己的bug。)
  • 如果您希望_loadFoo设置缺少的数组元素(使用附属效果)或返回foo属性的默认值,那么您没有想到。由于你在__get中通过引用返回,我想你想要一个实际的变量而不仅仅是一个返回值,所以我选择了第一条路线。你有_loadFoo做两件事 - 设置缺少的数组索引并返回值;为了使你没有直接设置数组索引的事情复杂化,你依赖于重载。

更正版本:

<?php

abstract class mainclass {

    var $vardata = array();

    function &__get ($var) {
        if (isset($this->vardata[$var])) return $this->vardata[$var];
        if ($var == 'foo') {
            $this->_loadFoo(); /* called for collaterals */
            return $this->foo;
        }
        return NULL;
    }

    abstract function _loadFoo();

    function __set ($var, $val) {
        $this->vardata[$var] = $val;
    }

    function __unset($var) {
        unset($this->vardata[$var]);
    }

}

class extender extends mainclass {

    function __construct() {

        var_dump($this->foo);
        $this->_loadFoo();
        echo '<br>';
        var_dump($this->foo);

    }

    function _loadFoo () {

        unset($this->foo);
        $this->foo = array();

        $this->foo[] = 'apples';
        $this->foo[] = 'oranges';
        $this->foo[] = 'pears';

    }

}

$test = new extender;