Navigation

Modeling BSON Data

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',
]

The type map above will convert BSON documents and arrays to MongoDB\Model\BSONDocument and MongoDB\Model\BSONArray objects, respectively. The root and document keys are used to distinguish the top-level BSON document from embedded documents, respectively.

A type map may specify any class that implements MongoDB\BSON\Unserializable as well as "array", "stdClass”, and "object" ("stdClass” and "object" are aliases of one another).

See also

Deserialization from BSON in the PHP manual

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 MongoDB\BSON\ObjectId $id;
    private string $name;
    private MongoDB\BSON\UTCDateTime $createdAt;

    public function __construct(string $name)
    {
        $this->id = new MongoDB\BSON\ObjectId;
        $this->name = $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.

Working with Enums

Backed enums can be used with BSON and will serialize as their case value (i.e. integer or string). Pure enums, which have no backed cases, cannot be directly serialized. This is similar to how enums are handled by json_encode().

Round-tripping a backed enum through BSON requires special handling. In the following example, the bsonUnserialize() method in the class containing the enum is responsible for converting the value back to an enum case:

<?php

enum Role: int
{
    case USER = 1;
    case ADMIN = 2;
}

class User implements MongoDB\BSON\Persistable
{
    public function __construct(
        private string $username,
        private Role $role,
        private MongoDB\BSON\ObjectId $_id = new MongoDB\BSON\ObjectId(),
    ) {}

    public function bsonSerialize(): array
    {
        return [
            '_id' => $this->_id,
            'username' => $this->username,
            'role' => $this->role,
        ];
    }

    public function bsonUnserialize(array $data): void
    {
        $this->_id = $data['_id'];
        $this->username = $data['username'];
        $this->role = Role::from($data['role']);
    }
}

Enums are prohibited from implementing MongoDB\BSON\Unserializable and MongoDB\BSON\Persistable, since enum cases have no state and cannot be instantiated like ordinary objects. Pure and backed enums can, however, implement MongoDB\BSON\Serializable, which can be used to overcome the default behavior whereby backed enums are serialized as their case value and pure enums cannot be serialized.

←   Example Data Stable API  →