2012年8月7日火曜日

phpで$hoge->fuga['ok'] = 1;を可能にする方法

結論:__get()の& 参照渡し が重要
class A {
    private $_data;
    public function __get($name)
    {
        return $this->_data[$name];
    }

    public function __set($name, $value)
    {
        $this->_data[$name] = $value;
    }
}

$a = new A;
$a->hoge = 1;
echo $a->hoge;  // 1

// 以下はエラーにはならないが、期待通りに動かない
$a->hoge['a'] = 1;
echo $a->hoge['a']; // null

// 上記は一度ゲッター(__get)から$_data['hoge']を引き出す際に
// コピーしてから['a']=1を設定してるので、インスタンス内の変数に影響を及ぼせない。
// リファレンスを使う。
class B {
    private $_data;
    public function & __get($name)
    {
        // メソッド定義時の"&"により返り値が参照返しになる
        return $this->_data[$name];
    }

    public function __set($name, $value)
    {
        $this->_data[$name] = $value;
    }
}
$b = new B;
$b->hoge['a'] = 1;
echo $b->hoge['a']; // 1
ただし副作用として思わぬところでデータを変更しちゃうかも。 使い分けが重要か。