1

I have an object that implements ArrayAccess, Iterator and Countable. That produces a nigh-perfect array masking. I can access it with offsets ($object[foo]), I can throw it into a foreach-loop, and many other things.

But what I can't do is give it to the native array iterator functions (next(), reset(), current(), key()), even though I have implemented the required methods from Iterator. PHP seems to stubbornly try to iterate through its member variables, and entirely disregards the iterator-methods.

Is there an interface that would hook the object to the remaining array-traversing-functions, or am I stuck with what I have?

Update: IteratorAggregate doesn't seem to be the answer either. While it is used in foreach-loops, the basic array iterator functions don't call the methods.

3 Answers 3

5

Recent changes in PHP prevent ArrayIterators form being manipulated using the standard array functions (reset, next, etc).

This should be restored soon: http://news.php.net/php.internals/42015

Sign up to request clarification or add additional context in comments.

Comments

3

One way to get this to work is to define your own iterator in a separate class, and then tell your main class to use that new iterator instead of the default one.

class MyIterator implements Iterator {
  public function key() {
    //
  }

  public function rewind() {
    //
  }

  // etc.

}

class MyMainClass implements IteratorAggregate {
  private $_data = array();

  // getIterator is required for the IteratorAggregate interface.
  public function getIterator() {
    return new MyIterator($this->_data);
  }

  // etc.

}

Then you should have as much control as you need. (And you can reuse your own MyIterator across a number of classes).

No testing done on the above, but the principle is correct, I believe.

Hope this helps!

3 Comments

For some strange reason, this doesn't work for me. It's as if the custom iterator never gets called with the basic array iterator functions.
The ArrayObject implementation already has a get/set convention for the Iterator
Sure, but ArrayObject is a concrete class, not an interface, so you have to extend it, not implement it. And, given that you can only extend from one class, I'd choose to do it this way. Better separation of concerns too, I think. YMMV :)
0

Is ArrayIterator not what you're looking for? Or what about ArrayObject, which seems to be SPL's interface for what you're trying to achieve.

1 Comment

Actually, those are not interfaces, but implementations. But, now that you mention it, ArrayObject does seem to react as expected to function calls such as reset($arrayObject);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.