Php 未在ArrayObject中调用偏移集

Php 未在ArrayObject中调用偏移集,php,arrayobject,Php,Arrayobject,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

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

为什么Test2不调用offsetSet方法?

ArrayObject
是一个很大的魔法,因此我不建议使用它,或者更糟糕的是,扩展它

但是您的实际问题与
ArrayObject
本身无关。您遇到的是
$s['b']['c']=
是所谓的对
'b'
偏移量的间接修改。PHP为其执行的代码大致如下所示:

$offset =& $s['b'];
$offset['c'] = ...;

正如您所看到的,偏移量
'b'
从未直接写入。相反,它是通过引用获取的,并且引用被修改。这就是为什么会调用
offsetGet
,而不是
offsetSet

对于多维数组,请参见用户提供的注释这是一种“陷阱”,因为我认为预期行为将与问题中的OP一样

此外,当作为对象或数组访问ArrayObject时,行为不一致

例如:

$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);
    }
}
使用OPs示例:

代码:

产出:

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"
    }
  }
}

这无法修复间接呼叫。感谢您分享您的经验!
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"
    }
  }
}