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, theMongoDB\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::getDatabase()
).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\Unserializableas well as"array"
, "stdClass
", and "object"
("stdClass
" and "object"
are aliases of one another).See also:
Deserialization from BSONin the PHP manual
Persistable Classes
The extension's persistence specificationoutlines how classes implementing its MongoDB\BSON\Persistableinterface are serialized to and deserialized from BSON. The Persistableinterface is analogous to PHP's Serializable interface.
The extension automatically handles serialization and deserialization for classes implementing the Persistableinterface 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 Persistableobject 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 specificationbut it bears repeating.
Consider the following class definition:
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:
$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\Persistablemay only be used for root and embedded BSON documents. It may not be used for BSON arrays.
Working with Enums
Backed enumscan 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:
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\Unserializableand 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.