@@ -18,7 +18,7 @@ Overview
18
18
When the driver executes a query or command (e.g.
19
19
:manual:`aggregate </reference/command/aggregate>`), results from the operation
20
20
are returned via a :php:`MongoDB\\Driver\\Cursor <class.mongodb-driver-cursor>`
21
- object. The Cursor class implements PHP's :php:`Traversable <traversable >`
21
+ object. The Cursor class implements PHP's :php:`Iterator <iterator >`
22
22
interface, which allows it to be iterated with ``foreach`` and interface with
23
23
any PHP functions that work with :php:`iterables <types.iterable>`. Similar to
24
24
result objects in other database drivers, cursors in MongoDB only support
@@ -35,20 +35,21 @@ While normal cursors can be iterated once with ``foreach``, that approach will
35
35
not work with tailable cursors. When ``foreach`` is used with a tailable cursor,
36
36
the loop will stop upon reaching the end of the initial result set. Attempting
37
37
to continue iteration on the cursor with a second ``foreach`` would throw an
38
- exception, since PHP attempts to rewind the cursor.
38
+ exception, since PHP attempts to rewind the cursor. Therefore, reading from a
39
+ tailable cursor will require direct usage of the :php:`Iterator <iterator>` API.
39
40
40
- In order to continuously read from a tailable cursor, we will need to wrap the
41
- Cursor object with an :php:`IteratorIterator <iteratoriterator>`. This will
42
- allow us to directly control the cursor's iteration (e.g. call ``next()``),
43
- avoid inadvertently rewinding the cursor, and decide when to wait for new
44
- results or stop iteration entirely.
41
+ .. note::
42
+
43
+ Before version 1.9.0 of the ``ext-mongodb`` extension, the cursor class does
44
+ not implement the :php:`Iterator <iterator>` interface. To manually iterate
45
+ a cursor using the method below, it must first be wrapped with an
46
+ :php:`IteratorIterator <iteratoriterator>`.
45
47
46
- Wrapping a Normal Cursor
47
- ------------------------
48
+ Manually Iterating a Normal Cursor
49
+ ----------------------------------
48
50
49
- Before looking at how a tailable cursor can be wrapped with
50
- :php:`IteratorIterator <iteratoriterator>`, we'll start by examining how the
51
- class interacts with a normal cursor.
51
+ Before looking at how a tailable cursor can be iterated, we'll start by
52
+ examining how the ``Iterator`` methods interact with a normal cursor.
52
53
53
54
The following example finds five restaurants and uses ``foreach`` to view the
54
55
results:
@@ -74,7 +75,7 @@ not occurred, the iterator then advances to the next position, control jumps
74
75
back to the validity check, and the loop continues.
75
76
76
77
With the inner workings of ``foreach`` under our belt, we can now translate the
77
- preceding example to use IteratorIterator :
78
+ preceding example to use the Iterator methods directly :
78
79
79
80
.. code-block:: php
80
81
@@ -84,28 +85,26 @@ preceding example to use IteratorIterator:
84
85
85
86
$cursor = $collection->find([], ['limit' => 5]);
86
87
87
- $iterator = new IteratorIterator($ cursor);
88
+ $cursor->rewind( );
88
89
89
- $iterator->rewind();
90
-
91
- while ($iterator->valid()) {
92
- $document = $iterator->current();
90
+ while ($cursor->valid()) {
91
+ $document = $cursor->current();
93
92
var_dump($document);
94
- $iterator ->next();
93
+ $cursor ->next();
95
94
}
96
95
97
96
.. note::
98
97
99
- Calling ``$iterator ->next()`` after the ``while`` loop naturally ends would
98
+ Calling ``$cursor ->next()`` after the ``while`` loop naturally ends would
100
99
throw an exception, since all results on the cursor have been exhausted.
101
100
102
101
The purpose of this example is simply to demonstrate the functional equivalence
103
102
between ``foreach`` and manual iteration with PHP's :php:`Iterator <iterator>`
104
- API. For normal cursors, there is little reason to use IteratorIterator instead
105
- of a concise ``foreach`` loop.
103
+ API. For normal cursors, there is little reason to manually iterate results
104
+ instead of a concise ``foreach`` loop.
106
105
107
- Wrapping a Tailable Cursor
108
- --------------------------
106
+ Iterating a Tailable Cursor
107
+ ---------------------------
109
108
110
109
In order to demonstrate a tailable cursor in action, we'll need two scripts: a
111
110
"producer" and a "consumer". The producer script will create a new capped
@@ -154,7 +153,7 @@ If you execute this consumer script, you'll notice that it quickly exhausts all
154
153
results in the capped collection and then terminates. We cannot add a second
155
154
``foreach``, as that would throw an exception when attempting to rewind the
156
155
cursor. This is a ripe use case for directly controlling the iteration process
157
- using :php:`IteratorIterator <iteratoriterator>` .
156
+ using the :php:`Iterator <iterator>` interface .
158
157
159
158
.. code-block:: php
160
159
@@ -167,17 +166,15 @@ using :php:`IteratorIterator <iteratoriterator>`.
167
166
'maxAwaitTimeMS' => 100,
168
167
]);
169
168
170
- $iterator = new IteratorIterator($cursor);
171
-
172
- $iterator->rewind();
169
+ $cursor->rewind();
173
170
174
171
while (true) {
175
- if ($iterator ->valid()) {
176
- $document = $iterator ->current();
172
+ if ($cursor ->valid()) {
173
+ $document = $cursor ->current();
177
174
printf("Consumed document created at: %s\n", $document->createdAt);
178
175
}
179
176
180
- $iterator ->next();
177
+ $cursor ->next();
181
178
}
182
179
183
180
Much like the ``foreach`` example, this version on the consumer script will
0 commit comments