We released a new version of the MongoDB driver for PHP (the
mongodb extension) near the end of last year. In a previous blog post, I covered the back story of the how and why we undertook this effort. And in another post, I spoke about the architecture of the new driver. In this episode I will discuss changes in cursor behaviour.
I recently found the following comment added to the driver's documentation, on PHP.net, which read:
I noticed that
->sortis missing from the cursor. Seems like the old driver has more functionality.
The new driver certainly allows for sorting of results of queries, but no longer by calling the
sort() method on the cursor object. This is because cursors are now created differently than in the old
In the old driver, the cursor would not really be created until after the first
rewind() call on the iterator:
<?php $m = new MongoClient; // Select 'demo' database and 'example' collection $collection = $m->demo->example; // Create the cursor $cursor = $collection->find();
At this moment, although a cursor object had been created, the query had not yet executed (i.e. it was not sent to the server). The query would only be executed by starting iteration with
foreach ( $cursor as $result ) or calling
$cursor->rewind(). This gives you the chance to configure the cursor's query with
skip() before it is executed by the server:
// Add sort, and limit $cursor->sort( [ 'name' => 1 ] )->limit( 40 );
After the cursor starts iterating (through
->rewind()), you can no longer call the aforementioned methods, as well as other methods that configure the query, to modify the cursor.
In the new driver, as soon as you have a \MongoDB\Driver\Cursor object, it has already been processed by the server. Because sort (and limit and skip) parameters need to be sent to the server before the query is executed, you can not retroactively call them on an existing
<?php $m = new \MongoDB\Driver\Manager(); $ns = 'demo.example'; // Create query object with all options: $query = new \MongoDB\Driver\Query( , // query (empty: select all) [ 'sort' => [ 'name' => 1 ], 'limit' => 40 ] // options ); // Execute query and obtain cursor: $cursor = $manager->executeQuery( $ns, $query );