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