Working with __get() by reference

女生的网名这么多〃 提交于 2019-12-23 14:23:04

问题


With an example class such as this:

class Test{
    public function &__get($name){
        print_r($name);
    }
}

An instance of Test will kick back output as such:

$myTest = new Test;
$myTest->foo['bar']['hello'] = 'world';
//outputs only foo

Is there a way I can get more information about what dimension of the array is being accessed, showing me (from the previous example) that the bar element of foo, and the hello element of bar are being targeted?


回答1:


You can't with the current implementation. In order for this to work, you will have to create an array object (i.e.: an object that implements ArrayAccess). Something like:

class SuperArray implements ArrayAccess {
    protected $_data = array();
    protected $_parents = array();

    public function __construct(array $data, array $parents = array()) {
        $this->_parents = $parents;
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $value = new SuperArray($value, array_merge($this->_parents, array($key)));
            }
            $this[$key] = $value;
        }
    }

    public function offsetGet($offset) {
        if (!empty($this->_parents)) echo "['".implode("']['", $this->_parents)."']";
        echo "['$offset'] is being accessed\n";
        return $this->_data[$offset];
    } 

    public function offsetSet($offset, $value) {
        if ($offset === '') $this->_data[] = $value;
        else $this->_data[$offset] = $value;
    } 

    public function offsetUnset($offset) {
        unset($this->_data[$offset]);
    } 

    public function offsetExists($offset) {
        return isset($this->_data[$offset]);
    } 
}

class Test{
    protected $foo;

    public function __construct() {
        $array['bar']['hello'] = 'world';
        $this->foo = new SuperArray($array); 
    }

    public function __get($name){
        echo $name.' is being accessed.'.PHP_EOL;
        return $this->$name;
    }
}

$test = new Test;
echo $test->foo['bar']['hello'];

Should output:

foo is being accessed.
['bar'] is being accessed
['bar']['hello'] is being accessed
world



回答2:


No you can't. $myTest->foo['bar']['hello'] = 'world'; goes through the following translation $myTest->__get('foo')['bar']['hello'] = 'world'; breaking them in parts become

$tmp = $myTest->__get('foo')
$tmp['bar']['hello'] = 'world';

What you can do is to create an ArrayAccess Derived Object. Where you define your own offsetSet() and return that from __get()




回答3:


Instead of returning an array, you could return an object that implements ArrayAccess. Objects are always returned and passed by reference. This pushes the problem at least on level down.



来源:https://stackoverflow.com/questions/4527175/working-with-get-by-reference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!