Работа с __get () по ссылке - PullRequest
       33

Работа с __get () по ссылке

4 голосов
/ 24 декабря 2010

С примером класса, таким как этот:

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

Экземпляр Test отбросит вывод в следующем виде:

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

Есть ли способ получить большеинформация о том, к какому измерению массива обращаются, показывая мне (из предыдущего примера), что элемент bar из foo и элемент hello из bar являются целевыми?

Ответы [ 3 ]

3 голосов
/ 24 декабря 2010

Вы не можете с текущей реализацией. Чтобы это работало, вам нужно будет создать объект массива (т.е. объект, реализующий ArrayAccess). Что-то вроде:

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'];

Должен вывести:

foo is being accessed.
['bar'] is being accessed
['bar']['hello'] is being accessed
world
1 голос
/ 24 декабря 2010

Вместо возврата массива вы можете вернуть объект, который реализует ArrayAccess .Объекты всегда возвращаются и передаются по ссылке.Это подталкивает проблему, по крайней мере, на уровень ниже.

1 голос
/ 24 декабря 2010

Нет, ты не можешь. $myTest->foo['bar']['hello'] = 'world'; выполняет следующий перевод $myTest->__get('foo')['bar']['hello'] = 'world'; разбивая их на части становятся

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

Что вы можете сделать, это создать ArrayAccess Производный объект. Где вы определяете свой offsetSet() и возвращаете его из __get()

...