mirror of
https://github.com/php/doc-en.git
synced 2026-03-23 23:32:18 +01:00
added to global.ent via f8bdf4030e
Sorry translators for this extra work!
Note: Notes containing 'windows.php.net/downloads/pecl/releases' were
removed as the associated entity will disappear one day via https://github.com/php/doc-base/pull/143
993 lines
32 KiB
XML
993 lines
32 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
|
|
<chapter xml:id="mongodb.architecture" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<titleabbrev>Driver Architecture and Internals</titleabbrev>
|
|
<title>Explains the driver architecture, and special features</title>
|
|
|
|
<section xml:id="mongodb.overview">
|
|
<titleabbrev>Architecture</titleabbrev>
|
|
<title>Architecture Overview</title>
|
|
|
|
<para>
|
|
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.
|
|
</para>
|
|
|
|
<para>
|
|
<mediaobject>
|
|
<alt>
|
|
MongoDB 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 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.svg" width="625" depth="450" format="SVG" />
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
|
|
<para>
|
|
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="&url.packagist.package;/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 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, queries, and write operations</member>
|
|
<member>Handling cursors for command and query results</member>
|
|
</simplelist>
|
|
</para>
|
|
|
|
<para>
|
|
<table>
|
|
<title>Driver Source Code and JIRA Projects</title>
|
|
<tgroup cols="3">
|
|
<thead>
|
|
<row>
|
|
<entry>Project</entry>
|
|
<entry>GitHub</entry>
|
|
<entry>JIRA</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>PHP Library</entry>
|
|
<entry><link xlink:href="&url.mongodb.github.phplib;">mongodb/mongo-php-library</link></entry>
|
|
<entry><link xlink:href="&url.mongodb.jira.phplib;">PHPLIB</link></entry>
|
|
</row>
|
|
<row>
|
|
<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>
|
|
</section>
|
|
|
|
<section xml:id="mongodb.connection-handling">
|
|
<titleabbrev>Connections</titleabbrev>
|
|
<title>Connection handling and persistence</title>
|
|
|
|
&mongodb.note.forking;
|
|
|
|
<section>
|
|
<title>Connection and topology persistence (PHP version since 1.2.0)</title>
|
|
|
|
<para>
|
|
All versions of the extension since 1.2.0 persist the
|
|
<link xlink:href="&url.mongodb.libmongoc;">libmongoc</link> client object in
|
|
the PHP worker process, which allows it to re-use database connections,
|
|
authentication states, <emphasis>and</emphasis> topology information across
|
|
multiple requests.
|
|
</para>
|
|
|
|
<para>
|
|
When <methodname>MongoDB\Driver\Manager::__construct</methodname> is
|
|
invoked, a hash is created from its arguments (i.e. URI string and array
|
|
options). The extension 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. This behavior can be disabled
|
|
via the <literal>"disableClientPersistence"</literal> driver option.
|
|
</para>
|
|
|
|
<para>
|
|
Each client contains its own database connections and a view of the server
|
|
topology (e.g. standalone, replica set, shard cluster). By persisting the
|
|
client between PHP requests, the extension is able to re-use established
|
|
database connections and remove the need for
|
|
<link xlink:href="&url.mongodb.sdam;">discovering the server topology</link>
|
|
on each request.
|
|
</para>
|
|
|
|
<para>
|
|
Consider the following example:
|
|
</para>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$managers = [
|
|
new MongoDB\Driver\Manager('mongodb://127.0.0.1'),
|
|
new MongoDB\Driver\Manager('mongodb://127.0.0.1'),
|
|
new MongoDB\Driver\Manager('mongodb://127.0.0.1:27017'),
|
|
new MongoDB\Driver\Manager('mongodb://rs1.example.com,rs2.example.com/', ['replicaSet' => 'myReplicaSet']),
|
|
];
|
|
|
|
foreach ($managers as $manager) {
|
|
$manager->executeCommand('test', new MongoDB\Driver\Command(['ping' => 1]));
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
|
|
<para>
|
|
The first two Manager objects will share the same
|
|
<link xlink:href="&url.mongodb.libmongoc;">libmongoc</link> client since
|
|
their constructor arguments are identical. The third and fourth objects will
|
|
each use their own client. In total, three clients will be created and the
|
|
PHP worker executing this script will open two connections to
|
|
<literal>127.0.0.1</literal> and one connection to each of
|
|
<literal>rs1.example.com</literal> and <literal>rs2.example.com</literal>.
|
|
If the extension discovers additional members of the replica set after
|
|
issuing <literal>hello</literal> commands, it will open additional
|
|
connections to those servers as well.
|
|
</para>
|
|
|
|
<para>
|
|
If the same worker executes the script again in a second request, the three
|
|
clients will be re-used and no new connections will be made. Depending on
|
|
how long ago the previous request was served, the extension may need to
|
|
issue additional <literal>hello</literal> commands to update its view of the
|
|
topologies.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Socket persistence (PHP versions before 1.2.0)</title>
|
|
|
|
<para>
|
|
Versions of the extension before 1.2.0 utilize PHP's Streams API for
|
|
database connections, using an API within
|
|
<link xlink:href="&url.mongodb.libmongoc;">libmongoc</link> to designate
|
|
custom handlers for socket communication; however, a new libmongoc client is
|
|
created for each <classname>MongoDB\Driver\Manager</classname>. As a result,
|
|
the extension persists individual database connections but not
|
|
authentication state or topology information. This means that the extension
|
|
needs to issue commands at the start of each request to authenticate and
|
|
<link xlink:href="&url.mongodb.sdam;">discover the server topology</link>.
|
|
</para>
|
|
|
|
<para>
|
|
Database connections are persisted by a hash derived from the server's
|
|
host, port, and the URI string used to construct the
|
|
<classname>MongoDB\Driver\Manager</classname>. The constructor's array
|
|
options are not included in this hash.
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
Versions of the extension >= 1.1.8 and < 1.2.0 do not persist sockets
|
|
for SSL connections. See
|
|
<link xlink:href="&url.mongodb.jira.phpc;-720">PHPC-720</link> for
|
|
additional information.
|
|
</simpara>
|
|
</note>
|
|
|
|
<para>
|
|
Despite its shortcomings with persisting SSL connections when and topology
|
|
information, this version of the extension supports all
|
|
<link linkend="context.ssl">SSL context options</link> since it uses
|
|
PHP's Streams API.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section xml:id="mongodb.persistence">
|
|
<titleabbrev>Persisting Data</titleabbrev>
|
|
<title>Serialization and deserialization of PHP variables into MongoDB</title>
|
|
|
|
<para>
|
|
This document discusses how compound structures (i.e. documents, arrays, and
|
|
objects) are converted between BSON and PHP values.
|
|
</para>
|
|
|
|
<section xml:id="mongodb.persistence.serialization">
|
|
<title>Serialization to BSON</title>
|
|
|
|
<section>
|
|
<title>Arrays</title>
|
|
|
|
<para>
|
|
If an array is a <emphasis>packed array</emphasis> — i.e. empty array or
|
|
the keys start at 0 and are sequential without gaps: <emphasis>BSON
|
|
array</emphasis>.
|
|
</para>
|
|
|
|
<para>
|
|
If the array is not packed — i.e. having associative (string) keys, the
|
|
keys don't start at 0, or when there are gaps:: <emphasis>BSON
|
|
object</emphasis>
|
|
</para>
|
|
|
|
<para>
|
|
A top-level (root) document, <emphasis>always</emphasis> serializes as a
|
|
BSON document.
|
|
</para>
|
|
|
|
<section>
|
|
<title>Examples</title>
|
|
|
|
<para>
|
|
These serialize as a BSON array:
|
|
</para>
|
|
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
[ 8, 5, 2, 3 ] => [ 8, 5, 2, 3 ]
|
|
[ 0 => 4, 1 => 9 ] => [ 4, 9 ]
|
|
]]>
|
|
</programlisting>
|
|
|
|
<para>
|
|
These serialize as a BSON document:
|
|
</para>
|
|
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
[ 0 => 1, 2 => 8, 3 => 12 ] => { "0" : 1, "2" : 8, "3" : 12 }
|
|
[ "foo" => 42 ] => { "foo" : 42 }
|
|
[ 1 => 9, 0 => 10 ] => { "1" : 9, "0" : 10 }
|
|
]]>
|
|
</programlisting>
|
|
|
|
<para>
|
|
Note that the five examples are <emphasis>extracts</emphasis> of a full
|
|
document, and represent only <emphasis>one</emphasis> value inside a
|
|
document.
|
|
</para>
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Objects</title>
|
|
|
|
<para>
|
|
If an object is of the <classname>stdClass</classname> class, serialize
|
|
as a <emphasis>BSON document</emphasis>.
|
|
</para>
|
|
|
|
<para>
|
|
If an object is a supported class that implements
|
|
<interfacename>MongoDB\BSON\Type</interfacename>, then use the BSON
|
|
serialization logic for that specific type.
|
|
<interfacename>MongoDB\BSON\Type</interfacename> instances (excluding
|
|
<interfacename>MongoDB\BSON\Serializable</interfacename> may only be
|
|
serialized as a document field value. Attempting to serialize such an
|
|
object as a root document will throw a
|
|
<classname>MongoDB\Driver\Exception\UnexpectedValueException</classname>
|
|
</para>
|
|
|
|
<para>
|
|
If an object is of an unknown class implementing the
|
|
<interfacename>MongoDB\BSON\Type</interfacename> interface, then throw a
|
|
<classname>MongoDB\Driver\Exception\UnexpectedValueException</classname>
|
|
</para>
|
|
|
|
<para>
|
|
If an object is of any other class, without implementing any special
|
|
interface, serialize as a <emphasis>BSON document</emphasis>. Keep only
|
|
<emphasis>public</emphasis> properties, and ignore
|
|
<emphasis>protected</emphasis> and <emphasis>private</emphasis>
|
|
properties.
|
|
</para>
|
|
|
|
<para>
|
|
If an object is of a class that implements the
|
|
<interfacename>MongoDB\BSON\Serializable</interfacename> interface, call
|
|
<methodname>MongoDB\BSON\Serializable::bsonSerialize</methodname> and use
|
|
the returned array or <classname>stdClass</classname> to serialize as a
|
|
BSON document or array. The BSON type will be determined by the following:
|
|
</para>
|
|
|
|
<para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>Root documents must be serialized as a BSON
|
|
document.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<interfacename>MongoDB\BSON\Persistable</interfacename> objects must be
|
|
serialized as a BSON document.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
If <methodname>MongoDB\BSON\Serializable::bsonSerialize</methodname>
|
|
returns a packed array, serialize as a BSON array.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
If <methodname>MongoDB\BSON\Serializable::bsonSerialize</methodname>
|
|
returns a non-packed array or <classname>stdClass</classname>,
|
|
serialize as a BSON document.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
If <methodname>MongoDB\BSON\Serializable::bsonSerialize</methodname>
|
|
did not return an array or <classname>stdClass</classname>, throw an
|
|
<classname>MongoDB\Driver\Exception\UnexpectedValueException</classname>
|
|
exception.
|
|
</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
|
|
<para>
|
|
If an object is of a class that implements the
|
|
<interfacename>MongoDB\BSON\Persistable</interfacename> interface (which
|
|
implies <interfacename>MongoDB\BSON\Serializable</interfacename>), obtain
|
|
the properties in a similar way as in the previous paragraphs, but
|
|
<emphasis>also</emphasis> add an additional property
|
|
<property>__pclass</property> as a Binary value, with subtype
|
|
<literal>0x80</literal> and data bearing the fully qualified class name
|
|
of the object that is being serialized.
|
|
</para>
|
|
|
|
<para>
|
|
The <property>__pclass</property> property is added to the array or
|
|
object returned by
|
|
<methodname>MongoDB\BSON\Serializable::bsonSerialize</methodname>, which
|
|
means it will overwrite any <property>__pclass</property> key/property in
|
|
the <methodname>MongoDB\BSON\Serializable::bsonSerialize</methodname>
|
|
return value. If you want to avoid this behaviour and set your own
|
|
<property>__pclass</property> value, you must <emphasis>not</emphasis>
|
|
implement <interfacename>MongoDB\BSON\Persistable</interfacename> and
|
|
should instead implement
|
|
<interfacename>MongoDB\BSON\Serializable</interfacename> directly.
|
|
</para>
|
|
|
|
<section>
|
|
<title>Examples</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class stdClass
|
|
{
|
|
public $foo = 42;
|
|
} // => {"foo": 42}
|
|
|
|
class MyClass
|
|
{
|
|
public $foo = 42;
|
|
protected $prot = 'wine';
|
|
private $fpr = 'cheese';
|
|
} // => {"foo": 42}
|
|
|
|
class AnotherClass1 implements MongoDB\BSON\Serializable
|
|
{
|
|
public $foo = 42;
|
|
protected $prot = 'wine';
|
|
private $fpr = 'cheese';
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return ['foo' => $this->foo, 'prot' => $this->prot];
|
|
}
|
|
} // => {"foo": 42, "prot": "wine"}
|
|
|
|
class AnotherClass2 implements MongoDB\BSON\Serializable
|
|
{
|
|
public $foo = 42;
|
|
|
|
public function bsonSerialize(): self
|
|
{
|
|
return $this;
|
|
}
|
|
} // => MongoDB\Driver\Exception\UnexpectedValueException("bsonSerialize() did not return an array or stdClass")
|
|
|
|
class AnotherClass3 implements MongoDB\BSON\Serializable
|
|
{
|
|
private $elements = ['foo', 'bar'];
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return $this->elements;
|
|
}
|
|
} // => {"0": "foo", "1": "bar"}
|
|
|
|
/**
|
|
* Nesting Serializable classes
|
|
*/
|
|
|
|
class AnotherClass4 implements MongoDB\BSON\Serializable
|
|
{
|
|
private $elements = [0 => 'foo', 2 => 'bar'];
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return $this->elements;
|
|
}
|
|
} // => {"0": "foo", "2": "bar"}
|
|
|
|
class ContainerClass1 implements MongoDB\BSON\Serializable
|
|
{
|
|
public $things;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->things = new AnotherClass4();
|
|
}
|
|
|
|
function bsonSerialize(): array
|
|
{
|
|
return ['things' => $this->things];
|
|
}
|
|
} // => {"things": {"0": "foo", "2": "bar"}}
|
|
|
|
|
|
class AnotherClass5 implements MongoDB\BSON\Serializable
|
|
{
|
|
private $elements = [0 => 'foo', 2 => 'bar'];
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return array_values($this->elements);
|
|
}
|
|
} // => {"0": "foo", "1": "bar"} as a root class
|
|
// ["foo", "bar"] as a nested value
|
|
|
|
class ContainerClass2 implements MongoDB\BSON\Serializable
|
|
{
|
|
public $things;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->things = new AnotherClass5();
|
|
}
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return ['things' => $this->things];
|
|
}
|
|
} // => {"things": ["foo", "bar"]}
|
|
|
|
|
|
class AnotherClass6 implements MongoDB\BSON\Serializable
|
|
{
|
|
private $elements = ['foo', 'bar'];
|
|
|
|
function bsonSerialize(): object
|
|
{
|
|
return (object) $this->elements;
|
|
}
|
|
} // => {"0": "foo", "1": "bar"}
|
|
|
|
class ContainerClass3 implements MongoDB\BSON\Serializable
|
|
{
|
|
public $things;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->things = new AnotherClass6();
|
|
}
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return ['things' => $this->things];
|
|
}
|
|
} // => {"things": {"0": "foo", "1": "bar"}}
|
|
|
|
class UpperClass implements MongoDB\BSON\Persistable
|
|
{
|
|
public $foo = 42;
|
|
protected $prot = 'wine';
|
|
private $fpr = 'cheese';
|
|
|
|
private $data;
|
|
|
|
public function bsonUnserialize(array $data): void
|
|
{
|
|
$this->data = $data;
|
|
}
|
|
|
|
public function bsonSerialize(): array
|
|
{
|
|
return ['foo' => $this->foo, 'prot' => $this->prot];
|
|
}
|
|
} // => {"foo": 42, "prot": "wine", "__pclass": {"$type": "80", "$binary": "VXBwZXJDbGFzcw=="}}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</section>
|
|
</section>
|
|
</section>
|
|
|
|
<section xml:id="mongodb.persistence.deserialization">
|
|
<title>Deserialization from BSON</title>
|
|
|
|
&mongodb.warning.duplicate-keys;
|
|
|
|
<para>
|
|
The legacy <code>mongo</code> extension deserialized
|
|
both BSON documents and arrays as PHP arrays. While PHP arrays are
|
|
convenient to work with, this behavior was problematic because different
|
|
BSON types could deserialize to the same PHP value (e.g.
|
|
<literal>{"0": "foo"}</literal> and <literal>["foo"]</literal>) and make it
|
|
impossible to infer the original BSON type. By default, the
|
|
<code>mongodb</code> extension addresses this concern by ensuring that BSON
|
|
arrays and documents are converted to PHP arrays and objects, respectively.
|
|
</para>
|
|
<para>
|
|
For compound types, there are three data types:
|
|
</para>
|
|
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>root</term>
|
|
<listitem>
|
|
<para>
|
|
refers to the top-level BSON document <emphasis>only</emphasis>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>document</term>
|
|
<listitem>
|
|
<para>
|
|
refers to embedded BSON documents <emphasis>only</emphasis>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>array</term>
|
|
<listitem>
|
|
<para>
|
|
refers to a BSON array
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<para>
|
|
Besides the three collective types, it is also possible to configure
|
|
specific fields in your document to map to the data types mentioned below.
|
|
As an example, the following type map allows you to
|
|
map each embedded document within an <literal>"addresses"</literal> array to
|
|
an <classname>Address</classname> class <emphasis>and</emphasis> each
|
|
<literal>"city"</literal> field within those embedded address documents to
|
|
a <classname>City</classname> class:
|
|
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
[
|
|
'fieldPaths' => [
|
|
'addresses.$' => 'MyProject\Address',
|
|
'addresses.$.city' => 'MyProject\City',
|
|
],
|
|
]
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Each of those three data types, as well as the field specific mappings,
|
|
can be mapped against different PHP types. The possible mapping values
|
|
are:
|
|
</para>
|
|
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><emphasis>not set</emphasis> or <type>NULL</type> (default)</term>
|
|
<listitem>
|
|
<para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
A BSON array will be deserialized as a PHP <type>array</type>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
A BSON document (root or embedded) without a
|
|
<property>__pclass</property> property
|
|
<footnote xml:id="mongodb.pclass">
|
|
<para>
|
|
A __pclass property is only deemed to exist if
|
|
there exists a property with that name, and it is a Binary value,
|
|
and the sub-type of the Binary value is 0x80. If any of these three
|
|
conditions is not met, the __pclass property does not exist and
|
|
should be treated as any other normal property.
|
|
</para>
|
|
</footnote>
|
|
becomes a PHP <classname>stdClass</classname> object, with each
|
|
BSON document key set as a public <classname>stdClass</classname>
|
|
property.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
A BSON document (root or embedded) with a
|
|
<property>__pclass</property> property <footnoteref linkend="mongodb.pclass"/> becomes a PHP object of
|
|
the class name as defined by the <property>__pclass</property>
|
|
property.
|
|
</para>
|
|
<para>
|
|
If the named class implements the
|
|
<interfacename>MongoDB\BSON\Persistable</interfacename> interface,
|
|
then the properties of the BSON document, including the
|
|
<property>__pclass</property> property, are sent as an associative
|
|
array to the
|
|
<methodname>MongoDB\BSON\Unserializable::bsonUnserialize</methodname>
|
|
function to initialise the object's properties.
|
|
</para>
|
|
<para>
|
|
If the named class does not exist or does not implement the
|
|
<interfacename>MongoDB\BSON\Persistable</interfacename> interface,
|
|
<classname>stdClass</classname> will be used and each BSON document
|
|
key (including <property>__pclass</property>) will be set as a
|
|
public <classname>stdClass</classname> property.
|
|
</para>
|
|
<para>
|
|
The <property>__pclass</property> functionality relies on the
|
|
property being part of a retrieved MongoDB document. If you use a
|
|
<link linkend="mongodb-driver-query.construct-queryOptions">projection</link>
|
|
when querying for documents, you need to include the
|
|
<property>__pclass</property> field in the projection for this
|
|
functionality to work.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>"array"</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Turns a BSON array or BSON document into a PHP array. There will be no
|
|
special treatment of a <property>__pclass</property> property <footnoteref linkend="mongodb.pclass"/>,
|
|
but it may be set as an element in the returned array if it was
|
|
present in the BSON document.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>"object"</literal> or <literal>"stdClass"</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Turns a BSON array or BSON document into a
|
|
<classname>stdClass</classname> object. There will be no special
|
|
treatment of a <property>__pclass</property> property <footnoteref linkend="mongodb.pclass"/>, but it may
|
|
be set as a public property in the returned object if it was present
|
|
in the BSON document.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>"bson"</literal></term>
|
|
<listitem>
|
|
<para>
|
|
Turns a BSON array into a <classname>MongoDB\BSON\PackedArray</classname>
|
|
and a BSON document into a <classname>MongoDB\BSON\Document</classname>,
|
|
regardless of whether the BSON document has a <property>__pclass</property>
|
|
property <footnoteref linkend="mongodb.pclass"/>.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
The <literal>bson</literal> value is only available for the three root
|
|
types, not in the field specific mappings.
|
|
</simpara>
|
|
</note>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>any other string</term>
|
|
<listitem>
|
|
<para>
|
|
Defines the class name that the BSON array or BSON object should be
|
|
deserialized as. For BSON objects that include
|
|
<property>__pclass</property> properties, that class will take
|
|
priority.
|
|
</para>
|
|
|
|
<para>
|
|
If the named class does not exist, is not concrete (i.e. it is
|
|
abstract or an interface), or does not implement
|
|
<interfacename>MongoDB\BSON\Unserializable</interfacename> then an
|
|
<classname>MongoDB\Driver\Exception\InvalidArgumentException</classname>
|
|
exception is thrown.
|
|
</para>
|
|
|
|
<para>
|
|
If the BSON object has a <property>__pclass</property> property and
|
|
that class exists and implements
|
|
<interfacename>MongoDB\BSON\Persistable</interfacename> it will
|
|
supersede the class provided in the type map.
|
|
</para>
|
|
|
|
<para>
|
|
The properties of the BSON document, <emphasis>including</emphasis>
|
|
the <property>__pclass</property> property if it exists, will be sent
|
|
as an associative array to the
|
|
<methodname>MongoDB\BSON\Unserializable::bsonUnserialize</methodname>
|
|
function to initialise the object's properties.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<section xml:id="mongodb.persistence.typemaps">
|
|
<title>TypeMaps</title>
|
|
|
|
<para>
|
|
TypeMaps can be set through the
|
|
<methodname>MongoDB\Driver\Cursor::setTypeMap</methodname> method on a
|
|
<classname>MongoDB\Driver\Cursor</classname> object, or the
|
|
<literal>$typeMap</literal> argument of
|
|
<function>MongoDB\BSON\toPHP</function>,
|
|
<methodname>MongoDB\BSON\Document::toPHP</methodname>, and
|
|
<methodname>MongoDB\BSON\PackedArray::toPHP</methodname>. Each of the three
|
|
classes (<emphasis>root</emphasis>, <emphasis>document</emphasis>, and
|
|
<emphasis>array</emphasis>) can be individually set, in addition to the
|
|
field specific types.
|
|
</para>
|
|
|
|
<para>
|
|
If the value in the map is <type>NULL</type>, it means the same as the
|
|
<emphasis>default</emphasis> value for that item.
|
|
</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Examples</title>
|
|
|
|
<para>
|
|
These examples use the following classes:
|
|
</para>
|
|
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>MyClass</term>
|
|
<listitem>
|
|
<para>
|
|
which does <emphasis>not</emphasis> implement any interface
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>YourClass</term>
|
|
<listitem>
|
|
<para>
|
|
which implements
|
|
<interfacename>MongoDB\BSON\Unserializable</interfacename>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>OurClass</term>
|
|
<listitem>
|
|
<para>
|
|
which implements
|
|
<interfacename>MongoDB\BSON\Persistable</interfacename>
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>TheirClass</term>
|
|
<listitem>
|
|
<para>
|
|
which extends OurClass
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<para>
|
|
The <methodname>MongoDB\BSON\Unserializable::bsonUnserialize</methodname>
|
|
method of YourClass, OurClass, TheirClass iterate over the array and set
|
|
the properties without modifications. It <emphasis>also</emphasis> sets
|
|
the <literal>$unserialized</literal> property to &true;:
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function bsonUnserialize( array $map )
|
|
{
|
|
foreach ( $map as $k => $value )
|
|
{
|
|
$this->$k = $value;
|
|
}
|
|
$this->unserialized = true;
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
/* typemap: [] (all defaults) */
|
|
{ "foo": "yes", "bar" : false }
|
|
-> stdClass { $foo => 'yes', $bar => false }
|
|
|
|
{ "foo": "no", "array" : [ 5, 6 ] }
|
|
-> stdClass { $foo => 'no', $array => [ 5, 6 ] }
|
|
|
|
{ "foo": "no", "obj" : { "embedded" : 3.14 } }
|
|
-> stdClass { $foo => 'no', $obj => stdClass { $embedded => 3.14 } }
|
|
|
|
{ "foo": "yes", "__pclass": "MyClass" }
|
|
-> stdClass { $foo => 'yes', $__pclass => 'MyClass' }
|
|
|
|
{ "foo": "yes", "__pclass": { "$type" : "80", "$binary" : "MyClass" } }
|
|
-> stdClass { $foo => 'yes', $__pclass => Binary(0x80, 'MyClass') }
|
|
|
|
{ "foo": "yes", "__pclass": { "$type" : "80", "$binary" : "YourClass") }
|
|
-> stdClass { $foo => 'yes', $__pclass => Binary(0x80, 'YourClass') }
|
|
|
|
{ "foo": "yes", "__pclass": { "$type" : "80", "$binary" : "OurClass") }
|
|
-> OurClass { $foo => 'yes', $__pclass => Binary(0x80, 'OurClass'), $unserialized => true }
|
|
|
|
{ "foo": "yes", "__pclass": { "$type" : "44", "$binary" : "YourClass") }
|
|
-> stdClass { $foo => 'yes', $__pclass => Binary(0x44, 'YourClass') }
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
/* typemap: [ "root" => "MissingClass" ] */
|
|
{ "foo": "yes" }
|
|
-> MongoDB\Driver\Exception\InvalidArgumentException("MissingClass does not exist")
|
|
|
|
/* typemap: [ "root" => "MyClass" ] */
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "MyClass" } }
|
|
-> MongoDB\Driver\Exception\InvalidArgumentException("MyClass does not implement Unserializable interface")
|
|
|
|
/* typemap: [ "root" => "MongoDB\BSON\Unserializable" ] */
|
|
{ "foo": "yes" }
|
|
-> MongoDB\Driver\Exception\InvalidArgumentException("Unserializable is not a concrete class")
|
|
|
|
/* typemap: [ "root" => "YourClass" ] */
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "MongoDB\BSON\Unserializable" } }
|
|
-> YourClass { $foo => "yes", $__pclass => Binary(0x80, "MongoDB\BSON\Unserializable"), $unserialized => true }
|
|
|
|
/* typemap: [ "root" => "YourClass" ] */
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "MyClass" } }
|
|
-> YourClass { $foo => "yes", $__pclass => Binary(0x80, "MyClass"), $unserialized => true }
|
|
|
|
/* typemap: [ "root" => "YourClass" ] */
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "OurClass" } }
|
|
-> OurClass { $foo => "yes", $__pclass => Binary(0x80, "OurClass"), $unserialized => true }
|
|
|
|
/* typemap: [ "root" => "YourClass" ] */
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "TheirClass" } }
|
|
-> TheirClass { $foo => "yes", $__pclass => Binary(0x80, "TheirClass"), $unserialized => true }
|
|
|
|
/* typemap: [ "root" => "OurClass" ] */
|
|
{ foo: "yes", "__pclass" : { "$type": "80", "$binary": "TheirClass" } }
|
|
-> TheirClass { $foo => "yes", $__pclass => Binary(0x80, "TheirClass"), $unserialized => true }
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
/* typemap: [ 'root' => 'YourClass' ] */
|
|
{ foo: "yes", "__pclass" : { "$type": "80", "$binary": "YourClass" } }
|
|
-> YourClass { $foo => 'yes', $__pclass => Binary(0x80, 'YourClass'), $unserialized => true }
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
/* typemap: [ 'root' => 'array', 'document' => 'array' ] */
|
|
{ "foo": "yes", "bar" : false }
|
|
-> [ "foo" => "yes", "bar" => false ]
|
|
|
|
{ "foo": "no", "array" : [ 5, 6 ] }
|
|
-> [ "foo" => "no", "array" => [ 5, 6 ] ]
|
|
|
|
{ "foo": "no", "obj" : { "embedded" : 3.14 } }
|
|
-> [ "foo" => "no", "obj" => [ "embedded => 3.14 ] ]
|
|
|
|
{ "foo": "yes", "__pclass": "MyClass" }
|
|
-> [ "foo" => "yes", "__pclass" => "MyClass" ]
|
|
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "MyClass" } }
|
|
-> [ "foo" => "yes", "__pclass" => Binary(0x80, "MyClass") ]
|
|
|
|
{ "foo": "yes", "__pclass" : { "$type": "80", "$binary": "OurClass" } }
|
|
-> [ "foo" => "yes", "__pclass" => Binary(0x80, "OurClass") ]
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
<programlisting role="text">
|
|
<![CDATA[
|
|
/* typemap: [ 'root' => 'object', 'document' => 'object' ] */
|
|
{ "foo": "yes", "__pclass": { "$type": "80", "$binary": "MyClass" } }
|
|
-> stdClass { $foo => "yes", "__pclass" => Binary(0x80, "MyClass") }
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
|
|
</section>
|
|
</section>
|
|
|
|
</section>
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|