なぜ次の
$a = new SplFixedArray(5);
$a[0] = array(1, 2, 3);
$a[0][0] = 12345; // here
var_dump($a);
生産する
Notice: Indirect modification of overloaded element of SplFixedArray has no effect in <file> on line <indicated>
バグですか?では、多次元SplFixedArraysをどのように扱いますか?回避策はありますか?
まず、問題はArrayAccess
を実装するすべてのクラスに関連しています。これはSplFixedArray
のみの特別な問題ではありません。
_[]
_演算子を使用してSplFixedArray
から要素にアクセスすると、配列とまったく同じように動作しません。内部的にはoffsetGet()
メソッドが呼び出され、あなたのケースでは配列-を返しますが、その配列への参照は返しません。これは、_$a[0]
_で行ったすべての変更は、保存しない限り失われることを意味します。
回避策:
_$a = new SplFixedArray(5);
$a[0] = array(1, 2, 3);
// get element
$element = $a[0];
// modify it
$element[0] = 12345;
// store the element again
$a[0] = $element;
var_dump($a);
_
これは スカラーを使用した例 であり、これも失敗します-配列要素のみに関連していないことを示すためです。
これは、offsetGet
の前で&
を平手打ちした場合に実際に修正可能です(ArrayAccess
実装の内部にアクセスできると仮定):
class Dict implements IDict {
private $_data = [];
/**
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset) {
return array_key_exists(self::hash($offset), $this->_data);
}
/**
* @param mixed $offset
* @return mixed
*/
public function &offsetGet($offset) {
return $this->_data[self::hash($offset)];
}
/**
* @param mixed $var
* @return string
*/
private static function hash($var) {
return is_object($var) ? spl_object_hash($var) : json_encode($var,JSON_UNESCAPED_SLASHES);
}
/**
* @param mixed $offset
* @param mixed $value
*/
public function offsetSet($offset, $value) {
$this->_data[self::hash($offset)] = $value;
}
/**
* @param mixed $offset
*/
public function offsetUnset($offset) {
unset($this->_data[self::hash($offset)]);
}
}
誰かに役立つ場合に備えて、同じエラーで私の経験を追加します:
最近、エラー許容度の低いフレームワーク(Laravel)にコードをインポートしました。その結果、存在しないキーを使用して連想配列から値を取得しようとすると、コードで例外がスローされるようになりました。これに対処するために、ArrayAccessインターフェイスを使用して独自の辞書を実装しようとしました。これは正常に機能しますが、次の構文は失敗します。
$myDict = new Dictionary();
$myDict[] = 123;
$myDict[] = 456;
そして、マルチマップの場合:
$properties = new Dictionary();
$properties['colours'] = new Dictionary();
$properties['colours'][] = 'red';
$properties['colours'][] = 'blue';
次の実装で問題を解決できました。
<?php
use ArrayAccess;
/**
* Class Dictionary
*
* DOES NOT THROW EXCEPTIONS, RETURNS NULL IF KEY IS EMPTY
*
* @package fnxProdCrawler
*/
class Dictionary implements ArrayAccess
{
// FOR MORE INFO SEE: http://alanstorm.com/php_array_access
protected $dict;
function __construct()
{
$this->dict = [];
}
// INTERFACE IMPLEMENTATION - ArrayAccess
public function offsetExists($key)
{
return array_key_exists($key, $this->dict);
}
public function offsetGet($key)
{
if ($this->offsetExists($key))
return $this->dict[$key];
else
return null;
}
public function offsetSet($key, $value)
{
// NOTE: THIS IS THE FIX FOR THE ISSUE "Indirect modification of overloaded element of SplFixedArray has no effect"
// NOTE: WHEN APPENDING AN ARRAY (E.G. myArr[] = 5) THE KEY IS NULL, SO WE TEST FOR THIS CONDITION BELOW, AND VOILA
if (is_null($key))
{
$this->dict[] = $value;
}
else
{
$this->dict[$key] = $value;
}
}
public function offsetUnset($key)
{
unset($this->dict[$key]);
}
}
それが役に立てば幸い。