==== BSON ==== .. default-domain:: mongodb .. contents:: On this page :local: :backlinks: none :depth: 1 :class: singlecol Overview -------- MongoDB stores data records as BSON documents. BSON is a binary representation of :term:`JSON` documents, though it contains more data types than JSON. For the BSON spec, see `bsonspec.org `_. By default, the |php-library| returns BSON documents as ``MongoDB\Model\BSONDocument`` objects and BSON arrays as ``MongoDB\Model\BSONArray`` objects. ``MongoDB\Model\BSONDocument`` and ``MongoDB\Model\BSONArray`` extend PHP's :php:`ArrayObject ` class and implement the MongoDB PHP driver's :php:`MongoDB\\BSON\\Serializable ` and :php:`MongoDB\\BSON\\Unserializable ` interfaces. Type Maps --------- Most methods that read data from MongoDB support a ``typeMap`` option, which allows control over how BSON is converted to PHP. Additionally, the :phpclass:`MongoDB\\Client`, :phpclass:`MongoDB\\Database`, and :phpclass:`MongoDB\\Collection` classes accept a ``typeMap`` option, which applies to any supporting methods and selected classes by default. The :phpclass:`MongoDB\\Client`, :phpclass:`MongoDB\\Database`, and :phpclass:`MongoDB\\Collection` classes use the following type map by default: .. code-block:: php [ 'array' => 'MongoDB\Model\BSONArray', 'document' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument', ] Serialization and deserialization of PHP variables into MongoDB --------------------------------------------------------------- ``Persistable`` Classes ~~~~~~~~~~~~~~~~~~~~~~~ The PHP driver's :php:`persistence ` specification specifies how classes implementing :php:`MongoDB\\BSON\\Persistable ` are serialized and deserialized, and is analogous to PHP's :php:`Serializable interface `. The PHP :php:`driver ` automatically handles serialization and deserialization for classes implementing ``MongoDB\BSON\Persistable`` without requiring the use of the ``typeMap`` option. Consider the following class definition: .. code-block:: php id = new MongoDB\BSON\ObjectID; $this->name = (string) $name; // Get current time in milliseconds since the epoch $msec = floor(microtime(true) * 1000); $this->createdAt = new MongoDB\BSON\UTCDateTime($msec); } function bsonSerialize() { return [ '_id' => $this->id, 'name' => $this->name, 'createdAt' => $this->createdAt, ]; } function bsonUnserialize(array $data) { $this->id = $data['_id']; $this->name = $data['name']; $this->createdAt = $data['createdAt']; } } The following constructs a ``Person`` object, inserts it into the database, and reads it back as an object of the same type: .. code-block:: php demo->persons; $result = $collection->insertOne(new Person('Bob')); $person = $collection->findOne(['_id' => $result->getInsertedId()]); var_dump($person); The output would then resemble: .. code-block:: none object(Person)#18 (3) { ["id":"Person":private]=> object(MongoDB\BSON\ObjectID)#15 (1) { ["oid"]=> string(24) "56fad2c36118fd2e9820cfc1" } ["name":"Person":private]=> string(3) "Bob" ["createdAt":"Person":private]=> object(MongoDB\BSON\UTCDateTime)#17 (1) { ["milliseconds"]=> int(1459278531218) } } The same document in the MongoDB shell might display as: .. code-block:: js { "_id" : ObjectId("56fad2c36118fd2e9820cfc1"), "__pclass" : BinData(128,"UGVyc29u"), "name" : "Bob", "createdAt" : ISODate("2016-03-29T19:08:51.218Z") } .. note:: :php:`MongoDB\\BSON\\Persistable ` may only be used for root and embedded BSON documents. BSON arrays are not supported. Emulating the Legacy Driver ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The legacy :php:`mongo extension ` returned both BSON documents and arrays as PHP arrays. While PHP arrays are convenient to work with, this behavior was problematic: - Different BSON types could deserialize to the same PHP value (e.g. ``{"0": "foo"}`` and ``["foo"]``), which made it impossible to infer the original BSON type. - Numerically-indexed PHP arrays would be serialized as BSON documents if there was a gap in their key sequence. Such gaps were easily caused by unsetting a key to remove an element and forgetting to reindex the array. The |php-library|'s ``MongoDB\Model\BSONDocument`` and ``MongoDB\Model\BSONArray`` classes address these concerns by preserving the BSON type information during serialization and deserialization; however, some users may still prefer the legacy behavior. If desired, you can use the ``typeMap`` option to have the library return everything as a PHP array: .. code-block:: php [ 'root' => 'array', 'document' => 'array', 'array' => 'array' ], ] ); $document = $client->demo->zips->findOne( ['_id' => '94301'], ['typeMap' => [ 'root' => 'array', 'document' => 'array', 'array' => 'array' ], ] ); var_dump($document); The above example would output something similar to: .. code-block:: php array(5) { ["_id"]=> string(5) "94301" ["city"]=> string(9) "PALO ALTO" ["loc"]=> array(2) { [0]=> float(-122.149685) [1]=> float(37.444324) } ["pop"]=> int(15965) ["state"]=> string(2) "CA" }