EDIT: Thanks to @jmikola feedback, it appears that a simple fix is to put the selectCollection call out of the generator function!

public function findBy($class, $id)
    $events = $this->events->selectCollection($class)->find([
        'emitter_id' => (string)$id,
    if (0 === $events->count()) {
        throw new NoResult;

    return $this->iterate($events);

private function iterate(\MongoCursor $events)
    foreach ($events as $event) {
        yield $this->serializer->unserialize($event);

MongoCollection::find returns MongoCursor instances.
Those are iterators.

Why on earth would I use a generator (which is an Iterator) for something that is an iterator already?
I can alrady iterate my results one by one, without loading everything in memory.

Well, as stated in another post, sometimes you have to do extra stuff on each result.
Hydration for example.

I could wrap the mongo iterator in a special iterator, that iterates over its internal iterator, and hydrates the current result before returning it.
BTW, there is a class for that! That’s what IteratorIterators are made for.

But Generators are made to avoid writing such Iterator classes by hand!

The problem

It’s all nice, but this won’t work, currently:

foreach ((new \MongoDB(new \MongoClient, 'test'))->selectCollection('test')->find(['provider_id' => (string)$id,]) as $document) {
     yield $this->serializer->unserialize($document);

And this is due to known issues, that are registered here:

The solution

Instead you have to fallback to the pre-generator era, and write your own IteratorIterator:

final class CursorIterator extends \IteratorIterator
    public function __construct(\Traversable $t, $serializer)
        $this->serializer = $serializer;

    public function current()
        return $this->serializer->unserialize(parent::current());


Generators are not yet the silver bullet :)
Of course, I’m not blaming anything nor anyone. It’s all pure happiness to be able to play with all this good work!
I’m just sharing my thoughts and experience.
Talking about that, I’d like to hear what @jmikola is thinking about that?

PS: You can also have a look at the complete implementation.