忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2017/05/01 15:18 |
Zend Framework2.1.4 Zend\Stdlib\ArrayObject
Zend Framework2.1.3のZend\Stdlib\ArrayObjectはクラスの中身が普通に書いてあったのですが、2.1.4にアップデートしてみたら中身がごっそり変わってました。

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


2013/04/03 23:07 | Comments(0) | PHP

コメント

コメントを投稿する






Vodafone絵文字 i-mode絵文字 Ezweb絵文字 (絵文字)



<<Zend Framework2.1.3 Zend\Stdlib\ArrayStack | HOME | Zend Framework2.1.3 Zend\Stdlib\ArrayObject>>
忍者ブログ[PR]