技術日記
PHPで__setを使ったプロパティに対する配列要素の追加Edit

PHP(5以降)で、

class Foo
{
protected $_vars = array();
public function __set($name, $value)
{
$this->_vars[$name] = $value;
}
public function __get($name)
{
return $this->_vars[$name];
}
}

みたいに、プロパティに対して__get()、__set()を使ってアクセスするようなクラスを作って、

$foo = new Foo();
$foo->bar[] = 'test';

みたいに、プロパティに対して配列要素追加の演算子を使った場合、昔は期待通りに動作していた($foo->bar == array(0 => 'test')になった)んだけど、最近のPHP(5.2.2)では期待したとおりには動作しなくなっていた(「Notice: Indirect modification of overloaded property Foo::$bar has no effect」になる)。確かに怪しい記法ではあったんだけど、これっていつから変更されていたのかな?

ググったら、関連情報としてPHP 5.2.0 で配列をオーバーロードするときの注意点 - PHPプロ!ニュースが見つかった。ArrayObjectって使ったことなかったけど、こういう使い道もあるのか。でも、なんかバッドノウハウ度が高くていやな書き方だなー。

あと、バグレポートでの関連議論「PHP Bugs: #39449: Overloaded array properties do not work correctly」。

まとめると、

  • PHP 5以降で__get()、__set()を使ってプロパティオーバーロードし、プロパティがarray型の値を持つ場合、それに対して利用できる演算子は制約を受ける($foo->bar[]= 〜や$foo->bar[$hoge] = 〜などは使えない)
  • プロパティオーバーロードを利用したarray型のプロパティを、従来の配列型プロパティと同じように操作したい場合、ArrayObject+ARRAY_AS_PROPSオプションを利用することで、ある程度対応できる(完全にネイティブ配列型プロパティ互換になるわけではない)
  • PHP 5.2以前に、プロパティオーバーロードを使って配列型プロパティを操作するコードを書いた記憶がある人は、関連コードの見直しをガンガレ! チョーガンガレ! Notice出力している開発環境だと気づきやすいけど、production環境だと結構気づきにくいバグになったりするぞ!

Published At2007-05-28 00:00Updated At2019-12-30 23:57