ArrayObject does not allow me to disable a value, and iterating over it

I have this notice:

ArrayIterator :: next (): the array has been changed outside of the object, and the internal position is no longer valid in / var / www ...

which is created by this code at the beginning of the foreach loop. With the notification, the foreach loop begins to repeat over and over. In other words, the internal position is reset whenever this happens. But according to php manual, ArrayObject uses ArrayIterator by default.

And the manual says about ArrayIterator

This iterator allows you to undo and change values ​​and keys when repeating arrays and objects.

Am I missing something? I found some posts about ArratIterator, but not like that. Is this a mistake or is it bad?

Version

: PHP Version 5.3.10-1ubuntu3.4

<?php //file 1: // no namespace abstract class holder extends \ArrayObject{ // abstract function init(); public function __construct($init){ parent::__construct($init, 1); } }?> <?php //file 2: namespace troops; class holder extends \holder{ public function __construct(){ parent::__construct($this->init()); } private function init(){ return array( /*... some data from db ...*/ ); } public function saveData(){ foreach($this as $k => $v){ $this->save($v); if($v->number_of_items==0) { unset($k); // $this->offsetUnset($k); // tryed both } } } } ?> 
+4
source share
3 answers

ArrayObject implements IteratorAggregate , which means it has a getIterator () method that returns an iterator.

php foreach loop will automatically load the iterator by calling the getIterator () method so that you can iterate over the iterator. This is convenient, but you need to get a reference to this iterator in order to call the offsetUnset () method on the iterator itself. The main thing here is to call the iterators offsetUnset () method, not the ArrayObjects offsetUnset () method.

 $ao = new ArrayObject(); $ao[] = 9; $iter = $ao->getIterator(); foreach ($iter as $k => $v) $iter->offsetUnset($k); // no error 

The base ArrayObject that iterates through the iteration will be mutated, so if you have more than one active iterator at the same time over the same Arrayobject, you will still encounter the same error.

The rationale for this is most likely that iterators can be memory efficient and should not copy the underlying ArrayObject because the copy is the only simple solution to the complex task of deciding what the current position of the iterator should be when things are added or removed from base array.

+7
source

If you delete the last record from the array, than the next foreach loop may fail (internal call $ this-> next ()) For example, if I have an array of one element and I will disconnect it than the next unsuccessful foreach.

So, this helped me verify the validity and break up the next loop in this case.

 deleteOffset = true; foreach ($iterator as $key => $value) { if ($deleteOffset && $iterator->offsetExists($key) ) { $iterator->offsetUnset($key); } //if remove last record than the foreach ( $this->next() ) fails so //we have to break in this case the next ->next call //after any ->offsetUnset calls if (!$iterator->valid()) break; } 
+1
source

It took me so long! I used the recipe on this page (unsuccessfully) to clear the contents of the ArrayObject repository, then I found this little diddy.

 $this->exchangeArray(array()); 

magic!

0
source

All Articles