开发者

Working with __get() by reference

开发者 https://www.devze.com 2023-02-01 06:23 出处:网络
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:

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'][开发者_JAVA百科'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?


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


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消