PHP 类将数据写入数组顶层之外的不可访问属性


PHP class write data to inaccessible property beyond the top level of an array

我什至不知道我正在尝试做的事情是否可行,但我想我会检查一下,看看我得到了什么回复。下面是该类的简单示例。

class MyClass {
    public $data = array();
    public function __construct($data) {
        $this->data = $data;
    }
    public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        return null;
    }
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
    public function setTestData($name, $value) {
        $this->data['test'][$name] = $value;
    }
}

我试图开始工作的是以下内容(注意:仅当它很容易并且不需要任何其他类或外部源即可工作时,并且数据数组始终保持类内的数组(:

$obj = new MyClass(array('test' => array()));
$obj->test->add = 'me';

我收到以下消息:

Notice: Indirect modification of overloaded property MyClass::$test has no effect in ...
Warning: Attempt to assign property of non-object in ...
Array
(
    [test] => Array
        (
        )
)

我还尝试更改__get以按引用传递,如下所示:

public function &__get($name) {

这似乎更接近,但仍然收到以下消息,这是有道理的,但不确定如何更改它以使其工作。

Warning: Attempt to assign property of non-object in ...

因此,如果以上所有内容都只是愚蠢或根本不是一个好主意,那么以下解决方案会是一个很好的替代解决方案吗?

$obj = new MyClass(array('test' => array()));
$obj->setTestData('add', 'me');

这按预期工作,甚至不使用魔术方法:

Array
(
    [test] => Array
        (
            [add] => me
        )
)

好吧,我希望有人能让我休息一下。感谢任何回复!


更新:其他替代方案:

仍然不完全是我想要的,但无论如何都很整洁。

class MyClass {
    public $data = array();
    public function __construct($data) {
        $this->data = $data;
    }
    public function __get($name) {
        if (!isset($this->data[$name])) {
            $this->data[$name] = new stdClass();
        } else if (is_array($this->data[$name])) {
            $this->data[$name] = @json_decode(@json_encode($this->data[$name], JSON_FORCE_OBJECT), false);
        }
        return $this->data[$name];
    }
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }
    public function toArray() {
        return @json_decode(@json_encode($this->data), true);
    }
}

因此,当我运行以下内容时:

$o = new MyClass(array('test' => array()));
$o->test->value = 10;
print_r($o->data);

我得到这个输出:

Array
(
    [test] => stdClass Object
        (
            [value] => 10
        )
)

然后,如果我需要它是一个数组,我只需运行以下命令:

printr($o->toArray());

获得:

Array
(
    [test] => Array
        (
            [value] => 10
        )
)

它也适用于任何深度(我喜欢(:

$o = new MyClass(array());
@$o->one->two->three->four->five = 100;
printr($o->toArray());

输出:

Array
(
    [one] => Array
        (
            [two] => Array
                (
                    [three] => Array
                        (
                            [four] => Array
                                (
                                    [five] => 100
                                )
                        )
                )
        )
)

唯一不喜欢的是我不得不使用 @ 来抑制这里的警告:

@$o->one->two->three->four->five = 100;

如果你不这样做,你会得到这个:

警告:从 中的空值创建默认对象...

我不知道。。大家怎么看?

简短的回答:你正在尝试的东西是用PHP无法实现的。


你可以想象这样的事情:

class MyClass {
    public $data = array();
    public function __get($name) {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        return null;
    }   
    public function __set($name, $value) {
        $this->data[$name] = $value;
    }   
}
$o = new MyClass();
$o->test->val = "foo";
var_dump($o);

这看起来stdClass它会为不存在(或无法访问!拥有对象后,您可以使用 -> 运算符访问或设置公共属性。

但它不起作用,因为您会收到以下消息:

PHP 通知:间接修改重载属性 MyClass::$test 对

它根本不在PHP中工作。代码需要如下所示:

$o = new MyClass();
$o->test = new stdClass();
$test = $o->test;
$test->val = "foo";
$o->test = $test;
var_dump($o);

注意!对于上面的示例,您不需要__get__set。您只需简单地为PHP对象赋值即可利用以下事实:可以向PHP对象添加公共属性。


另类:

这个替代方案呢:

class MyClass {
    public $data = array();
    public function data($key) {
        if(!isset($this->data[$key])) {
            $this->data[$key] = new stdClass();
        }
        return $this->data[$key];
    }
}
$o = new MyClass();
$o->data('test')->value = 10;