Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revisions to ext-mongodb architecture and library tutorial #2688

Merged
merged 3 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 35 additions & 75 deletions reference/mongodb/architecture.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,94 +10,60 @@
<title>Architecture Overview</title>

<para>
This section explains how all the different parts of the driver fit
together. From the different language runtimes, through the extension and
to the PHP libraries on top. This new architecture has replaced the old
<code>mongo</code> extension. We refer to the new one
as the <code>mongodb</code> extension.
This article explains how all the different components of the PHP driver fit
together, from base system libraries, through the extension, and to the PHP
libraries on top.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this article was originally adapted from a blog post. Much of that copy is no longer relevant to the audience, so I've removed references to the legacy extension API.

In addition to removing HHVM and PHP 5.x from the architecture diagram, I added libmongocrypt as a third system library dependency.

</para>

<para>
<mediaobject>
<alt>Architecture Diagram</alt>
<alt>
PHP Driver Architecture Diagram. The lowest level of the driver is our
system libraries: libmongoc, libbson, and libmongocrypt. The middle level
is the MongoDB PHP C extension. The upper level is PHP userland and
includes the MongoDB PHP library and higher-level packages such as
framework integrations and applications.
</alt>
<imageobject>
<imagedata fileref="en/reference/mongodb/images/driver_arch.png"/>
<imagedata fileref="en/reference/mongodb/images/driver_arch.svg" width="625" depth="450" format="SVG" />
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced the original PNG file with an SVG. There was prior art for this in the PHP manual:

doc-en/faq/passwords.xml

Lines 163 to 172 in 272838c

<mediaobject>
<alt>
The components of the value returned by password_hash and crypt: in
order, the chosen algorithm, the algorithm's options, the salt used,
and the hashed password.
</alt>
<imageobject>
<imagedata fileref="en/faq/figures/crypt-text-rendered.svg" width="690" depth="192" format="SVG" />
</imageobject>
</mediaobject>

Rendered: https://www.php.net/manual/en/faq.passwords.php#faq.password.storing-salts

</imageobject>
</mediaobject>
</para>

<para>
At the top of this stack sits a pure
<link xlink:href="&url.mongodb.library;">PHP library</link>, which we will
distribute as a Composer package. This library will provide an API similar
to what users have come to expect from the old mongo driver (e.g. CRUD methods,
database and collection objects, command helpers) and we expect it to be a
common dependency for most applications built with MongoDB. This library
will also implement common
<link xlink:href="&url.mongodb.specs;">specifications</link>, in the
interest of improving API consistency across all of the
<link xlink:href="&url.mongodb.drivers;">drivers</link> maintained by
MongoDB (and hopefully some community drivers, too).
At the top of this stack sits a
<link xlink:href="&url.mongodb.library;">PHP library</link>,
which is distributed as a
<link xlink:href="https://packagist.org/packages/mongodb/mongodb">Composer package</link>.
This library provides an API consistent with other MongoDB
<link xlink:href="&url.mongodb.drivers;">drivers</link>
and implements various cross-driver
<link xlink:href="&url.mongodb.specs;">specifications</link>.
While the extension can be used directly, the library has minimal overhead and
should be a common dependency for most applications built with MongoDB.
</para>

<para>
Sitting below that library we have the lower level driver.
This extension will effectively form the glue between PHP and our
system libraries (<link xlink:href="&url.mongodb.libmongoc;">libmongoc</link> and
<link xlink:href="&url.mongodb.libbson;">libbson</link>). This extension
will expose an identical public API for the most essential and
performance-sensitive functionality:
Sitting below that library is a PHP extension, which is distributed through
<link xlink:href="&url.pecl.package;mongodb">PECL</link>.
The extension forms the glue between PHP and our system libraries
(<link xlink:href="&url.mongodb.libmongoc;">libmongoc</link>,
<link xlink:href="&url.mongodb.libbson;">libbson</link>, and
<link xlink:href="&url.mongodb.libmongocrypt;">libmongocrypt</link>).
Its public API provides only the most essential functionality:

<simplelist>
<member>Connection management</member>
<member>BSON encoding and decoding</member>
<member>Object document serialization (to support ODM libraries)</member>
<member>Executing commands and write operations</member>
<member>Handling queries and cursors</member>
<member>Executing commands, queries, and write operations</member>
<member>Handling cursors for command and query results</member>
</simplelist>
</para>

<para>
By decoupling the driver internals and a high-level API into an extension and
PHP libraries, respectively, we hope to reduce our maintainence burden and
allow for faster iteration on new features. As a welcome side effect, this
also makes it easier for anyone to contribute to the driver. Additionally,
an identical public API will make it that much easier to port an
application across PHP runtimes, whether the application uses the low-level
driver directly or a higher-level PHP library.
</para>
<para>
<link xlink:href="&url.mongodb.docs.gridfs;">GridFS</link> is a great example
of why we chose this direction.
Although we implemented GridFS in C for our old mongo driver, it is actually
quite a high-level specification. Its API is just an abstraction for
accessing two collections: files (i.e. metadata) and chunks (i.e. blocks of
data). Likewise, all of the syntactic sugar found in the old mongo driver,
such as processing uploaded files or exposing GridFS files as PHP streams,
can be implemented in pure PHP. Provided we have performant methods for
reading from and writing to GridFS' collections – and thanks to our low
level extensions, we will – shifting this API to PHP is win-win.
</para>
<para>
Earlier I mentioned that we expect the PHP library to be a common
dependency for <emphasis>most</emphasis> applications, but not
<emphasis>all</emphasis>. Some users may prefer to stick to the no-frills
API offered by the extensions, or create their own high-level abstraction
(akin to <link xlink:href="&url.mongodb.doctrine;">Doctrine MongoDB</link> for
the old mongo driver). Future libraries could include a PHP library geared
for MongoDB administration, which provides an API for various user
management and ops commands. The next major version of
<link xlink:href="&url.mongodb.doctrine-odm;">Doctrine MongoDB ODM</link> will
likely also sit directly atop the extensions.
</para>
<para>
While we will continue to maintain and support the old mongo driver and its
users for the foreseeable future, we invite everyone to use the
next-generation driver and consider it for any new projects going forward.
You can find all of the essential components across GitHub and JIRA:

<table>
<title>Driver Source Code and JIRA Locations</title>
<title>Driver Source Code and JIRA Projects</title>
<tgroup cols="3">
<thead>
<row>
Expand All @@ -113,21 +79,14 @@
<entry><link xlink:href="&url.mongodb.jira.phplib;">PHPLIB</link></entry>
</row>
<row>
<entry>PHP 5 and PHP 7 Driver (phongo)</entry>
<entry>PHP Extension</entry>
<entry><link xlink:href="&url.mongodb.github.phpc;">mongodb/mongo-php-driver</link></entry>
<entry><link xlink:href="&url.mongodb.jira.phpc;">PHPC</link></entry>
</row>
</tbody>
</tgroup>
</table>
</para>

<para>
The existing <link xlink:href="&url.mongodb.jira;">PHP</link> project in JIRA
will remain open for reporting bugs against the old mongo driver, but we
would ask that you use the new projects above for anything pertaining to
our next-generation drivers.
</para>
</article>

<article xml:id="mongodb.connection-handling">
Expand All @@ -153,7 +112,8 @@
options). The driver will attempt to find a previously persisted
<link xlink:href="&url.mongodb.libmongoc;">libmongoc</link> client object for
that hash. If an existing client cannot be found for the hash, a new client
will be created (and persisted for future use).
will be created and persisted for future use. This behavior can be disabled
via the <literal>"disableClientPersistence"</literal> driver option.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't related to PHPC-2276, but it came up while reading through the same source file. IIRC we originally decided not to discuss this option anywhere other than the constructor docs, so I'm amenable to reverting this.

While re-reading this with fresh eyes, I just didn't like that the paragraph was so authoritative about clients always being persisted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explaining the full behaviour here makes sense 👍

</para>

<para>
Expand Down Expand Up @@ -203,7 +163,7 @@ foreach ($managers as $manager) {

<para>
If the same worker executes the script again in a second request, the three
clients will be re-used and no new connections should be made. Depending on
clients will be re-used and no new connections will be made. Depending on
how long ago the previous request was served, the driver may need to issue
additional <literal>hello</literal> commands to update its view of the
topologies.
Expand Down
Binary file removed reference/mongodb/images/driver_arch.png
Binary file not shown.
1 change: 1 addition & 0 deletions reference/mongodb/images/driver_arch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 13 additions & 14 deletions reference/mongodb/tutorial/library.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,16 @@ require 'vendor/autoload.php';
</para>

<para>
If you have previously used the old driver (i.e. <code>mongo</code>
extension), the library's API should look familiar. It contains a
If you have used MongoDB drivers in other languages, the library's API
should look familiar. It contains a
<link xlink:href="&url.mongodb.library.apidocs;/class/MongoDBClient/">Client</link>
class for connecting to MongoDB, and
class for connecting to MongoDB, a
<link xlink:href="&url.mongodb.library.apidocs;/class/MongoDBDatabase/">Database</link>
class for database-level operations (e.g. commands, collection management)
class for database-level operations (e.g. commands, collection management),
and a
<link xlink:href="&url.mongodb.library.apidocs;/class/MongoDBCollection">Collection</link>
class for collection-level operations (e.g.
<link xlink:href="&url.mongodb.wiki.crud;">CRUD</link> methods, index management).
Various Collection methods have been renamed for clarity, and to be in
accordance with a new language-agnostic
<link xlink:href="&url.mongodb.crud;">specification</link>.
</para>

<para>
Expand All @@ -117,15 +114,17 @@ echo "Inserted with Object ID '{$result->getInsertedId()}'";
</para>

<para>
Instead of injecting the generated <code>_id</code> field into the input
document (as was done in the old driver), it is now made available through
the result object returned by the <code>insertOne</code> method.
Since the inserted document did not contain an <code>_id</code> field, the
driver will generate an <classname>MongoDB\BSON\ObjectId</classname> for the
server to use as the <code>_id</code>. This value is also made available to
the caller via the result object returned by the <code>insertOne</code>
method.
</para>

<para>
After insertion, you can of course also query the data that you have just
inserted. For that, you use the <code>find</code> method, which returns an
iterable cursor:
After insertion, you can query for the data that you have just inserted.
For that, you use the <code>find</code> method, which returns an iterable
cursor:
<programlisting role="php">
<![CDATA[
<?php
Expand All @@ -149,7 +148,7 @@ foreach ($result as $entry) {
unserialized as type classes in the library by default. These classes ensure
that values preserve their type when being serialized back into BSON, which
avoids a caveat in the old driver where arrays might turn into documents,
and vice versa. Additionally, the classes extend
and vice versa. Additionally, these type classes extend
<classname>ArrayObject</classname> for enhanced usability. You can find more
information on how serialization and deserialization between PHP variables
and BSON is handled by the driver and library by reading the
Expand Down