Bug #68153 [Opn]: Iteration error, if use object with ArrayAccess
| From: | datibbaw@php.net | Date: | Mon, 06 Oct 2014 02:08:02 +0000 |
| Subject: | Bug #68153 [Opn]: Iteration error, if use object with ArrayAccess | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-187873@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=68153&edit=1
ID: 68153
Updated by: datibbaw@php.net
Reported by: zhuk2205 at gmail dot com
Summary: Iteration error, if use object with ArrayAccess
Status: Open
Type: Bug
Package: SPL related
Operating System: Mac OS
PHP Version: 5.5.17
Block user comment: N
Private report: N
New Comment:
You can get the same behaviour with this code:
$a = [1,2,3];
for (reset($a); ($key = key($a)) !== null; next($a)) {
unset($a[$key]);
}
var_dump($a); // [1] => 2
It's not recommended practice to remove elements from a collection while you iterate over it;
therefore I don't think we can consider this to be a bug.
Previous Comments:
------------------------------------------------------------------------
[2014-10-04 14:47:34] zhuk2205 at gmail dot com
Description:
------------
If create object and implement it ArrayAccess and Iterator interfaces, we have a problem with remove
elements from storage with use ArrayAccess.
Likely PHP \Iterator system not find "active" key after remove active element, and use key
as active next key. As result, in next iteration will be invalid key.
Test script:
---------------
<?php
class MyModel
{
}
class Collection implements \ArrayAccess, \Iterator
{
private $storage = array();
public function offsetExists($offset)
{
return isset($this->storage[$offset]);
}
public function offsetGet($offset)
{
return $this->storage[$offset];
}
public function offsetSet($offset, $value)
{
if (null === $offset) {
$this->storage[] = $value;
} else {
$this->storage[$offset] = $value;
}
}
public function offsetUnset($offset)
{
unset ($this->storage[$offset]);
}
public function current()
{
return current($this->storage);
}
public function next()
{
return next($this->storage);
}
public function key()
{
return key($this->storage);
}
public function valid()
{
return key($this->storage) !== null;
}
public function rewind()
{
reset($this->storage);
}
public function count()
{
return count($this->storage);
}
}
class MyCollectionModel
{
private $collection;
public function __construct()
{
$this->collection = new Collection();
}
public function addElement($element)
{
$this->collection[] = $element;
}
public function removeMyModels()
{
foreach ($this->collection as $index => $value) {
if ($value instanceof MyModel) {
unset ($this->collection[$index]);
}
}
}
}
// Create collection
$myCollection = new MyCollectionModel();
// Add own models to collections
for ($i = 0; $i < 10; $i++) {
$myCollection->addElement(new MyModel());
}
// Remove owl models from collection
$myCollection->removeMyModels();
// So, not all elements removed
print_r($myCollection);
Expected result:
----------------
Remove all "MyModel" instances from collection.
Actual result:
--------------
Not all removed objects.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68153&edit=1