Deserialization from BSON
The legacy mongo 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. {"0": "foo"} and ["foo"]) and make it impossible to infer the original BSON type. By default, the current driver addresses this concern by ensuring that BSON arrays and documents are converted to PHP arrays and objects, respectively.
For compound types, there are three data types:
- root
-
refers to the top-level BSON document only
- document
-
refers to embedded BSON documents only
- array
-
refers to a BSON array
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 "addresses" array to an Address class and each "city" field within those embedded address documents to a City class:
[ 'fieldPaths' => [ 'addresses.$' => 'MyProject\Address', 'addresses.$.city' => 'MyProject\City', ], ]
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:
- not set or NULL (default)
-
-
A BSON array will be deserialized as a PHP array.
-
A BSON document (root or embedded) without a __pclass property [1] becomes a PHP stdClass object, with each BSON document key set as a public stdClass property.
-
A BSON document (root or embedded) with a __pclass property [1] becomes a PHP object of the class name as defined by the __pclass property.
If the named class implements the MongoDB\BSON\Persistable interface, then the properties of the BSON document, including the __pclass property, are sent as an associative array to the MongoDB\BSON\Unserializable::bsonUnserialize() function to initialise the object's properties.
If the named class does not exist or does not implement the MongoDB\BSON\Persistable interface, stdClass will be used and each BSON document key (including __pclass) will be set as a public stdClass property.
The __pclass functionality relies on the property being part of a retrieved MongoDB document. If you use a projection when querying for documents, you need to include the __pclass field in the projection for this functionality to work.
-
- "array"
-
Turns a BSON array or BSON document into a PHP array. There will be no special treatment of a __pclass property [1], but it may be set as an element in the returned array if it was present in the BSON document.
- "object" or "stdClass"
-
Turns a BSON array or BSON document into a stdClass object. There will be no special treatment of a __pclass property [1], but it may be set as a public property in the returned object if it was present in the BSON document.
- any other string
-
Defines the class name that the BSON array or BSON object should be deserialized as. For BSON objects that include __pclass properties, that class will take priority.
If the named class does not exist, is not concrete (i.e. it is abstract or an interface), or does not implement MongoDB\BSON\Unserializable then an MongoDB\Driver\Exception\InvalidArgumentException exception is thrown.
If the BSON object has a __pclass property and that class exists and implements MongoDB\BSON\Persistable it will supersede the class provided in the type map.
The properties of the BSON document, including the __pclass property if it exists, will be sent as an associative array to the MongoDB\BSON\Unserializable::bsonUnserialize() function to initialise the object's properties.
TypeMaps
TypeMaps can be set through the MongoDB\Driver\Cursor::setTypeMap() method on a MongoDB\Driver\Cursor object, or the $typeMap argument of MongoDB\BSON\toPHP(). Each of the three classes (root, document, and array) can be individually set, in addition to the field specific types.
If the value in the map is NULL, it means the same as the default value for that item.
Examples
These examples use the following classes:
- MyClass
-
which does not implement any interface
- YourClass
-
which implements MongoDB\BSON\Unserializable
- OurClass
-
which implements MongoDB\BSON\Persistable
- TheirClass
-
which extends OurClass
The MongoDB\BSON\Unserializable::bsonUnserialize() method of YourClass, OurClass, TheirClass iterate over the array and set the properties without modifications. It also sets the $unserialized property to true:
<?php
function bsonUnserialize( array $map )
{
foreach ( $map as $k => $value )
{
$this->$k = $value;
}
$this->unserialized = true;
}
/* 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') }
/* 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 }
/* typemap: [ 'root' => 'YourClass' ] */ { foo: "yes", "__pclass" : { "$type": "80", "$binary": "YourClass" } } -> YourClass { $foo => 'yes', $__pclass => Binary(0x80, 'YourClass'), $unserialized => true }
/* 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") ]
/* typemap: [ 'root' => 'object', 'document' => 'object' ] */ { "foo": "yes", "__pclass": { "$type": "80", "$binary": "MyClass" } } -> stdClass { $foo => "yes", "__pclass" => Binary(0x80, "MyClass") }
Document créé le 30/01/2003, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/php-rf-mongodb.persistence.deserialization.html
L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.
Références
Ces références et liens indiquent des documents consultés lors de la rédaction de cette page, ou qui peuvent apporter un complément d'information, mais les auteurs de ces sources ne peuvent être tenus responsables du contenu de cette page.
L'auteur de ce site est seul responsable de la manière dont sont présentés ici les différents concepts, et des libertés qui sont prises avec les ouvrages de référence. N'oubliez pas que vous devez croiser les informations de sources multiples afin de diminuer les risques d'erreurs.