Zend Framework2.1.3のZend\Stdlib\ArrayObjectはクラスの中身が普通に書いてあったのですが、2.1.4にアップデートしてみたら中身がごっそり変わってました。
Zend\Stdlib\ArrayObject.phpの中身がたったこれだけに。
PHPのバージョンが5.3.4以降であればPhpReferenceCompatibilityを、それより前であればPhpLegacyCompatibilityをZend\Stdlib\AbstractArrayObjectと定義しています。
で、直後にZend\Stdlib\AbstractArrayObjectをextendsしただけのダミーのZend\Stdlib\ArrayObjectを作っています。
この結果、PHP5.3.4以降であればnew Zend\Stdlib\ArrayObjectの親クラスとしてPhpReferenceCompatibilityが、それより前であればPhpLegacyCompatibilityが設定されます。
複数の子クラスを作って必要に応じて選択するっていうのはStrategyパターンなんかがありますが、複数の親クラスから選択するのは何パターンって言うのですかね?
さてその中身はというと、PhpReferenceCompatibilityは、前回と同じくZend Frameworkで実装されたものです。
そしてPhpLegacyCompatibilityは単に\ArrayObjectを呼んでるだけでした。
結果として、PHP5.3.4より前であればPHPデフォルトの\ArrayObjectを、5.3.4以降であればZend Frameworkで実装したPhpReferenceCompatibilityを使うということで、何故か新しいバージョンの方にバグが入ってしまっているようです。
そして適当にさわってたら逆にZend\Stdlib\ArrayObjectのバグっぽいものを見つけました。
ArrayObject::STD_PROP_LISTはプロパティにforeachでアクセスできるよというフラグです。
つまり合わさるとforeachでプロパティと配列が両方出てくることになるはずなのですが、Zend\Stdlib\ArrayObjectでは配列の方しか出ません。
たぶんPhpReferenceCompatibility::__set($key, $value)にif($this->flag == self::ARRAY_AS_PROPS)って書いてるせいで足し算できてません。
まあSTD_PROP_LIST自体もおかしいんじゃねという話もあるので、実のところいったい何が正解なのかよくわからないんですけどね。
Zend\Stdlib\ArrayObject.phpの中身がたったこれだけに。
<?php namespace Zend\Stdlib; if (version_compare(PHP_VERSION, '5.3.4', 'lt')) { class_alias('Zend\Stdlib\ArrayObject\PhpLegacyCompatibility', 'Zend\Stdlib\AbstractArrayObject'); } else { class_alias('Zend\Stdlib\ArrayObject\PhpReferenceCompatibility', 'Zend\Stdlib\AbstractArrayObject'); } class ArrayObject extends AbstractArrayObject{}
PHPのバージョンが5.3.4以降であればPhpReferenceCompatibilityを、それより前であればPhpLegacyCompatibilityをZend\Stdlib\AbstractArrayObjectと定義しています。
で、直後にZend\Stdlib\AbstractArrayObjectをextendsしただけのダミーのZend\Stdlib\ArrayObjectを作っています。
この結果、PHP5.3.4以降であればnew Zend\Stdlib\ArrayObjectの親クラスとしてPhpReferenceCompatibilityが、それより前であればPhpLegacyCompatibilityが設定されます。
複数の子クラスを作って必要に応じて選択するっていうのはStrategyパターンなんかがありますが、複数の親クラスから選択するのは何パターンって言うのですかね?
さてその中身はというと、PhpReferenceCompatibilityは、前回と同じくZend Frameworkで実装されたものです。
そしてPhpLegacyCompatibilityは単に\ArrayObjectを呼んでるだけでした。
<?php namespace Zend\Stdlib\ArrayObject; use ArrayObject as PhpArrayObject; abstract class PhpLegacyCompatibility extends PhpArrayObject{ public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator'){ parent::__construct($input, $flags, $iteratorClass); } }
結果として、PHP5.3.4より前であればPHPデフォルトの\ArrayObjectを、5.3.4以降であればZend Frameworkで実装したPhpReferenceCompatibilityを使うということで、何故か新しいバージョンの方にバグが入ってしまっているようです。
そして適当にさわってたら逆にZend\Stdlib\ArrayObjectのバグっぽいものを見つけました。
<?php header('Content-type: text/html; charset=UTF-8'); require_once('path/to/channel/vendor/autoload.php'); // Zend\Stdlib\ArrayObject $arrayobject = new Zend\Stdlib\ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS | ArrayObject::STD_PROP_LIST); $arrayobject['a'] = 'aa'; $arrayobject->b = 'bb'; print($arrayobject->a); // NULL print($arrayobject->['b']); // NULL foreach($arrayobject as $key=>$val){ print($key); // aのみ } // \ArrayObject $default = new \ArrayObject(array(), \ArrayObject::ARRAY_AS_PROPS | \ArrayObject::STD_PROP_LIST); $default['a'] = 'aa'; $default->b = 'bb'; print($default->a); // aa print($default->['b']); // bb foreach($default as $key=>$val){ print($key); // a,b両方 }ArrayObject::ARRAY_AS_PROPSは配列にプロパティでアクセスできるよというフラグです。
ArrayObject::STD_PROP_LISTはプロパティにforeachでアクセスできるよというフラグです。
つまり合わさるとforeachでプロパティと配列が両方出てくることになるはずなのですが、Zend\Stdlib\ArrayObjectでは配列の方しか出ません。
たぶんPhpReferenceCompatibility::__set($key, $value)にif($this->flag == self::ARRAY_AS_PROPS)って書いてるせいで足し算できてません。
まあSTD_PROP_LIST自体もおかしいんじゃねという話もあるので、実のところいったい何が正解なのかよくわからないんですけどね。
PR