Navigation

BSON

Overview

MongoDB stores data records as BSON documents. BSON is a binary representation of JSON documents, though it contains more data types than JSON. For the BSON spec, see bsonspec.org.

By default, the MongoDB PHP Library returns BSON documents as MongoDB\Model\BSONDocument objects and BSON arrays as MongoDB\Model\BSONArray objects, respectively.

BSON Classes

MongoDB\Model\BSONArray

This class extends PHP’s ArrayObject class. It also implements PHP’s JsonSerializable interface and the driver’s MongoDB\BSON\Serializable and MongoDB\BSON\Unserializable interfaces.

By default, the library will deserialize BSON arrays as instances of this class. During BSON and JSON serialization, instances of this class will serialize as an array type (array_values() is used internally to numerically reindex the array).

MongoDB\Model\BSONDocument

This class extends PHP’s ArrayObject class. It also implements PHP’s JsonSerializable interface and the driver’s MongoDB\BSON\Serializable and MongoDB\BSON\Unserializable interfaces.

By default, the library will deserialize BSON documents as instances of this class. During BSON and JSON serialization, instances of this class will serialize as a document type (object casting is used internally).

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 MongoDB\Client, MongoDB\Database, and MongoDB\Collection classes accept a typeMap option, which can be used to specify a default type map to apply to any supporting methods and selected classes (e.g. MongoDB\Client::selectDatabase()).

The MongoDB\Client, MongoDB\Database, and MongoDB\Collection classes use the following type map by default:

[
    'array' => 'MongoDB\Model\BSONArray',
    'document' => 'MongoDB\Model\BSONDocument',
    'root' => 'MongoDB\Model\BSONDocument',
]

Persistable Classes

The driver’s persistence specification outlines how classes implementing its MongoDB\BSON\Persistable interface are serialized to and deserialized from BSON. The Persistable interface is analogous to PHP’s Serializable interface.

The driver automatically handles serialization and deserialization for classes implementing the Persistable interface without requiring the use of the typeMap option. This is done by encoding the name of the PHP class in a special property within the BSON document.

Note

When deserializing a PHP variable from BSON, the encoded class name of a Persistable object will override any class specified in the type map, but it will not override "array" and "stdClass" or "object". This is discussed in the persistence specification but it bears repeating.

Consider the following class definition:

<?php

class Person implements MongoDB\BSON\Persistable
{
    private $id;
    private $name;
    private $createdAt;

    public function __construct($name)
    {
        $this->id = new MongoDB\BSON\ObjectID;
        $this->name = (string) $name;
        $this->createdAt = new MongoDB\BSON\UTCDateTime;
    }

    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 example constructs a Person object, inserts it into the database, and reads it back as an object of the same type:

<?php

$collection = (new MongoDB\Client)->test->persons;

$result = $collection->insertOne(new Person('Bob'));

$person = $collection->findOne(['_id' => $result->getInsertedId()]);

var_dump($person);

The output would then resemble:

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:

{
  "_id" : ObjectId("56fad2c36118fd2e9820cfc1"),
  "__pclass" : BinData(128,"UGVyc29u"),
  "name" : "Bob",
  "createdAt" : ISODate("2016-03-29T19:08:51.218Z")
}

Note

MongoDB\BSON\Persistable may only be used for root and embedded BSON documents. It may not be used for BSON arrays.

Emulating the Legacy Driver

The legacy 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 numerically reindex the array.

The MongoDB PHP Library’s BSONDocument and 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:

<?php

$client = new MongoDB\Client(
    'mongodb://127.0.0.1/',
    [],
    [
        'typeMap' => [
            'array' => 'array',
            'document' => 'array',
            'root' => 'array',
        ],
    ]
);

$document = $client->test->zips->findOne(['_id' => '94301']);

var_dump($document);

The above example would output something similar to:

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"
}