2

Is there a way to iterate over an object's keys implementing ArrayAccess and Iterator interfaces? Array access works as a charm but I can't use foreach on those objects which would help me a lot. Is it possible? I have such code so far:

<?php
class IteratorTest implements ArrayAccess, Iterator {
  private $pointer = 0;

  public function offsetExists($index) {
    return isset($this->objects[$index]);
  }

  public function offsetGet($index) {
    return $this->objects[$index];
  }

  public function offsetSet($index, $newValue) {
    $this->objects[$index] = $newValue;
  }

  public function offsetUnset($index) {
    unset($this->objects[$index]);
  }

  public function key() {
    return $this->pointer;
  }

  public function current() {
    return $this->objects[$this -> pointer];
  }

  public function next() {
    $this->pointer++;
  }

  public function rewind() {
    $this->pointer = 0;
  }

  public function seek($position) {
    $this->pointer = $position;
  }

  public function valid() {
    return isset($this->objects[$this -> pointer]);
  }
}

$it = new IteratorTest();

$it['one'] = 1;
$it['two'] = 2;

foreach ($it as $k => $v) {
  echo "$k: $v\n";
}

// expected result:
// one: 1
// two: 2

Thanks for any help and hints.

2 Answers 2

3

I use this to implement Iterator. Maybe you can adapt it to your code ;)

class ModelList implements Iterator {
    public  $list;

    private $index = 0;

    public  $nb;

    public  $nbTotal;

    public function __construct() {
        $this->list    = [];
        $this->nb      = 0;
        $this->nbTotal = 0;

        return $this;
    }

    /**
     * list navigation
     */
    public function rewind() {
        $this->index = 0;
    }

    public function current() {
        $k   = array_keys( $this->list );
        $var = $this->list[ $k[ $this->index ] ];

        return $var;
    }

    public function key() {
        $k   = array_keys( $this->list );
        $var = $k[ $this->index ];

        return $var;
    }

    public function next() {
        $k = array_keys( $this->list );
        if ( isset( $k[ ++$this->index ] ) ) {
            $var = $this->list[ $k[ $this->index ] ];

            return $var;
        } else {
            return false;
        }
    }

    public function valid() {
        $k   = array_keys( $this->list );
        $var = isset( $k[ $this->index ] );

        return $var;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2
while ($it->valid()) {
    echo $it->key().' '.$it->current();
    $it->next();
}

Would be my approach, however, this function looks iffy:

 public function next() {
    $this->pointer++;
 }

Incrementing 'one' isn't likely to give you 'two'. Try the code in the answers to this question to get the next array key:

$keys = array_keys($this->objects);
$position = array_search($this->key(), $keys);
if (isset($keys[$position + 1])) {
    $this->pointer = $keys[$position + 1];
} else {
    $this->pointer = false;
}

1 Comment

Thanks for the tips but I need these objects working using foreach because they are being passed as arguments to other functions I can't modify. I have modified it a bit and it seems to work: http://ideone.com/rZjim

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.