Один из способов сделать это
<?php
$a = new ArrayObject();
$a['b'] = array('c' => array('d'));
$d =& $a['b'];
unset($d['c']);
print_r($a['b']);
печатает:
Array
(
)
Придется немного подумать, чтобы объяснить, почему синтаксис, который вы изначально использовали, не 't удалить элемент.
РЕДАКТИРОВАТЬ: объяснение поведения
Что происходит, вызов unset($a['b']['c']);
переводится в:
$temp = $a->offsetGet('b');
unset($temp['c']);
поскольку $temp
является копией $a
вместо ссылки на нее, PHP использует внутреннее копирование при записи и создает второй массив, в котором $temp
не имеет ['b']['c']
, но $a
все еще имеет.
ДРУГОЕ РЕДАКТИРОВАНИЕ: код многократного использования
Таким образом, независимо от того, каким образом вы его нарезаете, кажется, что попытка перегрузить function offsetGet($index)
на function &offsetGet($index)
приводит к проблемам;Итак, вот самый короткий вспомогательный метод, который я придумал, мог / мог бы добавить его как статический метод или метод экземпляра в подкласс ArrayObject
, независимо от того, что плавает на вашей лодке:
function unsetNested(ArrayObject $oArrayObject, $sIndex, $sNestedIndex)
{
if(!$oArrayObject->offSetExists($sIndex))
return;
$aValue =& $oArrayObject[$sIndex];
if(!array_key_exists($sNestedIndex, $aValue))
return;
unset($aValue[$sNestedIndex]);
}
Таким образом, исходный код станет
$a = new ArrayObject();
$a['b'] = array('c' => array('d'));
// instead of unset($a['b']['c']);
unsetNested($a, 'b', 'c');
print_r($a['b']);
ДАЙТЕ ДРУГОЕ РЕДАКТИРОВАНИЕ: OO Решение
ОК - Итак, я, должно быть, сегодня утром карабкался, потому что я обнаружил ошибку в своем коде, и когда пересмотрел,мы можем реализовать решение, основанное на ОО.
Просто чтобы вы знали, что я пробовал, расширение segfaults ..:
/// XXX This does not work, posted for illustration only
class BadMoxuneArrayObject extends ArrayObject
{
public function &offsetGet($index)
{
$var =& $this[$index];
return $var;
}
}
Реализация декоратора с другой стороны работает как шарм:
class MoxuneArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable
{
private $_oArrayObject; // Decorated ArrayObject instance
public function __construct($mInput=null, $iFlags=0, $sIteratorClass='')
{
if($mInput === null)
$mInput = array();
if($sIteratorClass === '')
$this->_oArrayObject = new ArrayObject($mInput, $iFlags);
else
$this->_oArrayObject = new ArrayObject($mInput, $iFlags, $sIteratorClass);
}
// -----------------------------------------
// override offsetGet to return by reference
// -----------------------------------------
public function &offsetGet($index)
{
$var =& $this->_oArrayObject[$index];
return $var;
}
// ------------------------------------------------------------
// everything else is passed through to the wrapped ArrayObject
// ------------------------------------------------------------
public function append($value)
{
return $this->_oArrayObject->append($value);
}
public function asort()
{
return $this->_oArrayObject->asort();
}
public function count()
{
return $this->_oArrayObject->count();
}
public function exchangeArray($mInput)
{
return $this->_oArrayObject->exchangeArray($mInput);
}
public function getArrayCopy()
{
return $this->_oArrayObject->getArrayCopy();
}
public function getFlags()
{
return $this->_oArrayObject->getFlags();
}
public function getIterator()
{
return $this->_oArrayObject->getIterator();
}
public function getIteratorClass()
{
return $this->_oArrayObject->getIteratorClass();
}
public function ksort()
{
return $this->_oArrayObject->ksort();
}
public function natcassesort()
{
return $this->_oArrayObject->natcassesort();
}
public function offsetExists($index)
{
return $this->_oArrayObject->offsetExists($index);
}
public function offsetSet($index, $value)
{
return $this->_oArrayObject->offsetSet($index, $value);
}
public function offsetUnset($index)
{
return $this->_oArrayObject->offsetUnset($index);
}
public function serialize()
{
return $this->_oArrayObject->serialize();
}
public function setFlags($iFlags)
{
return $this->_oArrayObject->setFlags($iFlags);
}
public function setIteratorClass($iterator_class)
{
return $this->_oArrayObject->setIteratorClass($iterator_class);
}
public function uasort($cmp_function)
{
return $this->_oArrayObject->uasort($cmp_function);
}
public function uksort($cmp_function)
{
return $this->_oArrayObject->uksort($cmp_function);
}
public function unserialize($serialized)
{
return $this->_oArrayObject->unserialize($serialized);
}
}
Теперь этот код работает так, как нужно:
$a = new MoxuneArrayObject();
$a['b'] = array('c' => array('d'));
unset($a['b']['c']);
var_dump($a);
Тем не менее, придется изменить какой-то код, хотя ..;Я не вижу никакого способа обойти это.