问题
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