PHP __set变量,而__get通过引用传递

时间:2012-02-24 10:11:50

标签: php getter-setter magic-methods

我认为这是一个非常简单的问题,但不确定。

我有一个班级:

<?PHP
class PropertyTest {
    private $data = array();

    public function __set($name, $value) {
        $this->data[$name] = $value;
    }

    public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
                ' in ' . $trace[0]['file'] .
                ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    public function __isset($name) {
        echo "Is '$name' set?\n";
        return isset($this->data[$name]);
    }

    public function __unset($name) {
        echo "Unsetting '$name'\n";
        unset($this->data[$name]);
    }

    public function getHidden() {
        return $this->hidden;
    }
}
?>

不知道为什么,但“代码”块无论如何都很烦人。

真正的基本魔法设置。但当我改变__get以通过引用传递时,我不能再这样做了:

$object->$variableName = $variableValue;

我不确定为什么虽然我假设因为它检查它是否存在但是由于它必须通过引用返回一些内容,如果它不存在则不会这样做。 set函数可能不会被调用,即使我返回一个伪值,它也永远不会调用set函数,因为它'已经存在/有一个值'。

我是否理解正确?如果是这样,有解决方法吗?如果不是,它是如何工作的,是否有解决方法?

1 个答案:

答案 0 :(得分:0)

除非我遗漏某些东西,否则它对我来说很好

<?php
class PropertyTest
{

    private $data = array();

    public function __set($name, $value)
    {
        $this->data[$name] = $value;
    }

    public function &__get($name)
    {
        if(array_key_exists($name, $this->data))
            return $this->data[$name];
        return null;
    }

    public function __isset($name) 
    {
        return isset($this->data[$name]);
    }

    public function __unset($name) 
    {
        unset($this->data[$name]);
    }

    public function getHidden()
    {
        return $this->hidden;
    }
}

$oPropTest = new PropertyTest();
$sField = 'my-field';

$oPropTest->$sField = 5;

var_dump($oPropTest);

<强>输出:

bash-3.2$ php test-get-set.php
object(PropertyTest)#1 (1) {
  ["data":"PropertyTest":private]=>
  array(1) {
    ["my-field"]=>
    int(5)
  }
}

我建议您__get实施的一个调整是利用__isset方法而不是重新执行检查(以不同的方式执行此操作)

public function __get($name)
{
    if($this->__isset($name))
        return $this->data[$name];
    return null;
}

关于__get的引用返回的想法;它可以工作,但对公共属性以外的任何东西都没用,因为私有和受保护的属性不能通过类范围外的引用直接设置。

$oPropTest = new PropertyTest();
$sField = 'my-field';

$oPropTest->$sField = 5;      // sets $oPropTest->my-field to 5 (effectively)
$iRef = $oPropTest->$sField;  // $iRef is a reference to $oPropTest->my-field
$iRef = 6;                    // this will not set $oPropTest->my-field since it's private