由于 ArrayIterator 不是一个真正的列表,因此“append”的实现让我有点困惑。当使用“append”时,我预计新值位于“最后一个元素索引 + 1”的位置。当您在之前取消设置元素时,这种情况不会发生。
看起来,一旦索引被使用,它们就会被列入黑名单,并且永远不会再使用,即使它们被取消设置也是如此。
正如在 https://php.net/manual/de/arrayiterator.offsetset.php#106775 中建议的那样,ArrayIterator::append 使用 ArrayIterator::offsetSet 且索引参数为空。所以我找到了以下两种解决方法来使“append”按我想要的方式工作。
<?php
class myArrayIterator extends ArrayIterator {
public function offsetSet($offset, $value) {
if (is_null($offset)) { // 当它被 ArrayIterator::append 调用时,offset == null
$offset = $this->generateOffset(); // 在单独的方法中执行
}
parent::offsetSet($offset, $value); // 使用索引调用原生实现
$this->ksort(); // 对其进行排序,以避免在转储或迭代时出现混淆
}
protected function generateOffset() {
$offset = count($this); // 将计数作为偏移量,因为它应该是 lastKey+1
while ($this->offsetExists($offset)) { // 它真的是空的?
$offset++; // 尝试下一个,直到找到一个空的
}
return $offset;
}
}
class mySaveArrayIterator extends myArrayIterator {
protected function generateOffset() {
$offset = 0; // 预计 0 是第一个可能的键
while ($this->offsetExists($offset)) { // 尝试每个键,直到找到一个空的
$offset++;
}
return $offset;
}
}
$data = array('foo', 'bar', 'baz');
$array = new ArrayIterator($data);
$myArray = new myArrayIterator($data);
$mySaveArray = new mySaveArrayIterator($data);
// 移除最后一个元素
$array ->offsetUnset(2);
$myArray ->offsetUnset(2);
$mySaveArray->offsetUnset(2);
// 追加一个元素
$array ->append('foobar');
$myArray ->append('foobar');
$mySaveArray->append('foobar');
// 检查新元素的位置
print_r($array);
print_r($myArray);
print_r($mySaveArray);
// 移除一些元素
$array ->offsetUnset(1);
$myArray ->offsetUnset(1);
$mySaveArray->offsetUnset(1);
// 再次追加一个元素
$array ->append('foobarbaz');
$myArray ->append('foobarbaz');
$mySaveArray->append('foobarbaz');
// 检查新元素的位置
print_r($array);
print_r($myArray);
print_r($mySaveArray);
?>
输出
ArrayIterator 对象
(
[storage:ArrayIterator:private] => 数组
(
[0] => foo
[1] => bar
[3] => foobar
)
)
myArrayIterator 对象
(
[storage:ArrayIterator:private] => 数组
(
[0] => foo
[1] => bar
[2] => foobar
)
)
mySaveArrayIterator 对象
(
[storage:ArrayIterator:private] => 数组
(
[0] => foo
[1] => bar
[2] => foobar
)
)
ArrayIterator 对象
(
[storage:ArrayIterator:private] => 数组
(
[0] => foo
[3] => foobar
[4] => foobarbaz
)
)
myArrayIterator 对象
(
[storage:ArrayIterator:private] => 数组
(
[0] => foo
[2] => foobar
[3] => foobarbaz
)
)
mySaveArrayIterator 对象
(
[storage:ArrayIterator:private] => 数组
(
[0] => foo
[1] => foobarbaz
[2] => foobar
)
)
这帮助我以串行的方式将 ArrayIterator 视为具有有效索引的列表。