示例php代码:
class TestArrayObject extends ArrayObject {
function offsetSet($index,$val){
echo $index.':'.$val.PHP_EOL;
}
}
$s = new TestArrayObject();
//test 1
$s['a'] = 'value';//calls offsetSet
//test 2
$s['b']['c'] = 'value';//does not call offsetSet, why?
var_dump($s);
为什么不测试2调用offsetSet方法?
答案 0 :(得分:2)
ArrayObject
是一大块魔法,因此我不建议使用它,或者 - 更糟糕的是 - 扩展它。
但您的实际问题本身与ArrayObject
无关。您遇到的是$s['b']['c'] = ...;
是'b'
偏移的所谓间接修改。 PHP为其执行的代码看起来大致如下:
$offset =& $s['b'];
$offset['c'] = ...;
正如您所见,偏移'b'
永远不会直接写入。而是通过引用获取并修改引用。这就是调用offsetGet
的原因,而不是offsetSet
。
答案 1 :(得分:0)
对于多维数组,请参阅用户提供的注释here
答案 2 :(得分:0)
这是一种“陷阱”,因为我认为预期的行为将与OP所述的行为有关。
此外,当将ArrayObject作为Object或Array访问时,行为不一致。
示例:
$foo['b']['c'] = 'value'; // no warning
var_dump($foo);
$bar->b->c = 'value'; // triggers warning
var_dump($bar);
我在扩展ArrayObject的类中遇到了同样的问题。我无法解决这个问题,但设法通过实现一个用于链接属性创建的新方法来解决这个问题。
class Arraylist extends ArrayObject
{
public function set($key, $value = null)
{
if (!is_null($value)) {
$val = new ArrayList((array) $value);
} else {
$val = new ArrayList();
}
$this->offsetSet($key, $val);
return $this->offsetGet($key);
}
public function offsetSet($index,$val){
echo $index.':'.$val.PHP_EOL;
parent::offsetSet($index, $val);
}
}
使用OP示例:
代码:
$s = new ArrayList();
$s->set('a', 'value');
$s->set('b')->set('c', 'another value');
var_dump($s);
输出:
0:value
a:ArrayList
0:value
b:ArrayList
0:another value
c:ArrayList
0:another value
class ArrayList#5 (2) {
public $a =>
class ArrayList#7 (1) {
string(5) "value"
}
public $b =>
class ArrayList#8 (1) {
public $c =>
class ArrayList#9 (1) {
string(13) "another value"
}
}
}