update : 2015.11.03
php.shukuma.com검색:
|
Serialisation and deserialisation of PHP variables into MongoDBThis document discusses the methods how compound structures (documents, arrays, objects) are persisted through the drivers. And how they are brought back into PHP land. Serialisation to BSONArraysIf an array is a packed array — i.e. the keys start at 0 and are sequential without gaps: BSON array. If the array is not packed — i.e. having associative (string) keys, the keys don't start at 0, or when there are gaps:: BSON object A top-level (root) document, always serializes as a BSON document. ExamplesThese serialize as a BSON array: [ 8, 5, 2, 3 ] => [ 8, 5, 2, 3 ] [ 0 => 4, 1 => 9 ] => [ 4, 9 ] These serialize as a BSON document: [ 0 => 1, 2 => 8, 3 => 12 ] => { "0" : 1, "2" : 8, "3" : 12 } [ "foo" => 42 ] => { "foo" : 42 } [ 1 => 9, 0 => 10 ] => { "1" : 9, "0" : 10 } Note that the five examples are extracts of a full document, and represent only one value inside a document. ObjectsIf an object is of the stdClass class, serialize as a BSON document. If an object is a supported class that implements MongoDB\BSON\Type, then use the BSON serialization logic for that specific type. MongoDB\BSON\Type instances (excluding MongoDB\BSON\Serializable may only be serialized as a document field value. Attempting to serialize such an object as a root document will throw a MongoDB\Driver\Exception\UnexpectedValueException If an object is of an unknown class implementing the MongoDB\BSON\Type interface, then throw a MongoDB\Driver\Exception\UnexpectedValueException If an object is of any other class, without implementing any special interface, serialize as a BSON document. Keep only public properties, and ignore protected and private properties. If an object is of a class that implements the MongoDB\BSON\Serializable interface, call bsonSerialize() and use the returned array or stdClass to serialize as a BSON document or array. The BSON type will be determined by the following:
If an object is of a class that implements the MongoDB\BSON\Persistable interface (which implies MongoDB\BSON\Serializable obtain the properties in a similar way as in the previous paragraphs, but also add an additional property __pclass as a Binary value, with subtype 0x80 and data bearing the fully qualified class name of the object that is being serialized. The __pclass property is added to the array or object returned by bsonSerialize(), which means it will overwrite any __pclass key/property in the bsonSerialize() return value. If you want to avoid this behaviour and set your own __pclass value, you must not implement MongoDB\BSON\Persistable and should instead implement MongoDB\BSON\Serializable directly. ExamplesstdClass { public $foo = 42; } => { "foo" : 42 } MyClass { public $foo = 42; protected $prot = "wine"; private $fpr = "cheese"; } => { "foo" : 42 } AnotherClass1 implements MongoDB\BSON\Serializable { public $foo = 42; protected $prot = "wine"; private $fpr = "cheese"; function bsonSerialize() { return [ 'foo' => $this->foo, 'prot' => $this->prot ]; } } => { "foo" : 42, "prot" : "wine" } AnotherClass2 implements MongoDB\BSON\Serializable { public $foo = 42; function bsonSerialize() { return $this; } } => MongoDB\Driver\Exception\UnexpectedValueException("bsonSerialize() did not return an array or stdClass") AnotherClass3 implements MongoDB\BSON\Serializable { private $elements = [ 'foo', 'bar' ]; function bsonSerialize() { return $this->elements; } } => { "0" : "foo", "1" : "bar" } ContainerClass implements MongoDB\BSON\Serializable { public $things = AnotherClass4 implements MongoDB\BSON\Serializable { private $elements = [ 0 => 'foo', 2 => 'bar' ]; function bsonSerialize() { return $this->elements; } } function bsonSerialize() { return [ 'things' => $this->things ]; } } => { "things" : { "0" : "foo", "2" : "bar" } } ContainerClass implements MongoDB\BSON\Serializable { public $things = AnotherClass5 implements MongoDB\BSON\Serializable { private $elements = [ 0 => 'foo', 2 => 'bar' ]; function bsonSerialize() { return array_values($this->elements); } } function bsonSerialize() { return [ 'things' => $this->things ]; } } => { "things" : [ "foo", "bar" ] } ContainerClass implements MongoDB\BSON\Serializable { public $things = AnotherClass6 implements MongoDB\BSON\Serializable { private $elements = [ 'foo', 'bar' ]; function bsonSerialize() { return (object) $this->elements; } } function bsonSerialize() { return [ 'things' => $this->things ]; } } => { "things" : { "0" : "foo", "1" : "bar" } } UpperClass implements MongoDB\BSON\Persistable { public $foo = 42; protected $prot = "wine"; private $fpr = "cheese"; function bsonSerialize() { return [ 'foo' => $this->foo, 'prot' => $this->prot ]; } } => { "foo" : 42, "prot" : "wine", "__pclass" : { "$type" : "80", "$binary" : "VXBwZXJDbGFzcw==" } } Deserialization from BSONFor compound types, there are three data types:
Each of those three data types can be mapped against different PHP types. The possible mapping values are:
TypeMapsTypeMaps 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. If the value in the map is NULL, it means the same as the default value for that item. ExamplesThese examples use the following classes:
The bsonUnserialize() method of YourClass, OurClass, TheirClass iterate over the array and set the properties without modifications. It also sets the $unserialized property to true: 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") } |