mate64
mate64

Reputation: 10082

Symfony2 Doctrine iterate over with while next()

I'm looking for a working solution, to iterate over a PersistentCollection in . Unfortunately this seems not to work? Symfony ignores the next() function!

while (($animal = $zooAnimals->next()) !== false) {

    $color = $animal->getColor();

    print_r($color); die; // Test and die
}

print_r('Where are the animals?'); die; // << Current result

Reference: Doctrine\ODM\MongoDB\PersistentCollection

Upvotes: 4

Views: 11263

Answers (4)

Ivan Moll
Ivan Moll

Reputation: 1

This is my solution,

$zooAnimals->getIterator();

while ($animal = $zooAnimals->current()) {

    echo $animal->getColor();

    $zooAnimals->next();
}

Upvotes: 0

Ara&#250;jo Everson
Ara&#250;jo Everson

Reputation: 75

Works to me!

$collection = new ArrayCollection();
$collection->add('Laranja');
$collection->add('Uva');
$collection->add('Morango');

do {
    print_r($collection->current());
} while ($collection->next());

Upvotes: 2

Touki
Touki

Reputation: 7525

This is not Symfony's "fault". This is a misunderstanding of how to iterate over an object. There are several ways to handle this for your use case. Here are some

Use a foreach!

Your PersistentCollection implements Collection which implements IteratorAggregate which implements Traversable (long way heh?).
An object which implements interface Traversable can be used in a foreach statement.

IteratorAggregate forces you to implement one method getIterator which must return an Iterator. This last also implements Traversable interface.

Usage of an iterator

Iterator interface forces your object to declare 5 methods in order to be used by a foreach

class MyCollection implements Iterator
{
    protected $parameters = array();
    protected $pointer = 0;

    public function add($parameter)
    {
        $this->parameters[] = $parameter;
    }

    /**
     * These methods are needed by Iterator
     */
    public function current()
    {
        return $this->parameters[$this->pointer];
    }

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

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

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

    public function valid()
    {
        return array_key_exists($this->pointer, $this->parameters);
    }
}

You can use any class which implements Iterator it like this - Demo file

$coll = new MyCollection;
$coll->add('foo');
$coll->add('bar');

foreach ($coll as $key => $parameter) {
    echo $key, ' => ', $parameter, PHP_EOL;
}

Use iterator with a while

In order to use this class like a foreach. Methods should be called this way - Demo file

$coll->rewind();

while ($coll->valid()) {
    echo $coll->key(), ' => ', $coll->current(), PHP_EOL;
    $coll->next();
}

Upvotes: 10

Mick
Mick

Reputation: 31939

Simple solution:

1 Convert your PersistentCollection to an array first

$zooAnimalsArray = $zooAnimals->toArray();

2 Handle the array classically like you would with any PHP arrays.

Note This has the advantage of creating code that doesn't depend too much on your database (in case you wish one day to switch to a relational database), you wouldn't have to rewrite everything.

Upvotes: 3

Related Questions