1

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メソッドを呼び出さないのはなぜですか?

4

3 に答える 3

2

ArrayObjectは魔法の大きな塊なので、それを使用したり、さらに悪いことに、拡張したりすることはお勧めしません。

しかし、あなたの実際の問題はそれ自体とは関係ありませんArrayObject。あなたが遭遇しているのは、オフセットの$s['b']['c'] = ...;いわゆる間接的な変更です。'b'PHPが実行するコードは、おおよそ次のようになります。

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

ご覧のとおり、オフセット'b'が直接書き込まれることはありません。代わりに、参照によってフェッチさ、参照が変更されます。そのためoffsetGet、ではなく呼び出されoffsetSetます。

于 2011-11-20T10:03:39.237 に答える
0

多次元配列については、ユーザー投稿のメモを参照してください。

于 2011-11-20T10:11:06.113 に答える
0

これは一種の「落とし穴」です。なぜなら、予想される動作は 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);
    }
}

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"
    }
  }
}
于 2012-12-30T17:14:53.423 に答える