Десеріалізація з BSON

Увага

Документи BSON технічно можуть містити ключі, що повторюються, оскільки документи зберігаються у вигляді списку пар ключ-значення; однак програмам слід утримуватися від створення документів з дублікатами ключів, оскільки поведінка сервера та драйвера може бути невизначеною. Оскільки об'єкти та масиви PHP не можуть мати ключів, що повторюються, дані також можуть бути втрачені при декодуванні документа BSON з повторюваними ключами.

Устаревший модульmongo десеріалізував як документи, так і масиви BSON як масиви PHP. Хоча з PHP масивами зручно працювати, така поведінка була проблематичною, оскільки різні типи BSON можуть десеріалізуватися до одного і того ж значення PHP (наприклад, {"0": "foo"}и["foo"]) і неможливо буде вивести оригінальний тип BSON. За промовчанням поточний драйвер вирішує цю проблему, забезпечуючи перетворення масивів та документів BSON на масиви та об'єкти PHP відповідно.

Для складових типів існує три типи даних:

root

відноситься тількик документу верхнего уровня BSON

document

відноситься тільки до вбудованих документів BSON

array

відноситься до масивів BSON

Крім трьох групових типів, можна налаштувати певні поля в документі для порівняння з типами даних, вказаними нижче. Як приклад, наступна карта типів дозволяє зіставити кожен вбудований документ у масиві "addresses" з класом Address акаждое поле"city" у цих документах із вбудованою адресою з класом City :

[ 'fieldPaths' => [ 'addresses.$' => 'MyProject\Address', 'addresses.$.city' => 'MyProject\City', ],]

Кожен із цих трьох типів даних, а також зіставлення для конкретних полів можуть бути зіставлені з різними типами PHP. Можливі значення зіставлення:

не вказаноили NULL (по умолчанию)

  • Масив BSON буде десеріалізовано, як PHP array.

  • Документ BSON (кореневий або впроваджений) без якості__pclass[1]стає об'єктом PHPstdClass, причому кожен ключ документа BSON встановлюється як відкрита властивістьstdClass

  • Документ BSON (кореневий або вбудований) з властивістю__pclass[1]стає об'єктом PHP імені класу, як це визначено властивістю__pclass.

    Якщо цей клас реалізує інтерфейс MMongoDB\BSON\Persistable, то властивості документа BSON, включаючи властивість__pclass, відправляються у вигляді асоціативного масиву у функціюMongoDB\BSON\Unserializable::bsonUnserialize() для ініціалізації властивостей об'єкта

    Якщо названий клас не існує або не реалізує інтерфейсMongoDB\BSON\Persistable, буде використовуватисяstdClass, і кожен ключ документа BSON (включаючи__pclass) буде встановлено як відкриту властивістьstdClass

    Функціональність__pclass залежить від того, чи є властивістю частиною вилученого документа MongoDB. Якщо ви використовуєтепроекціюпри запиті документів, потрібно включити поле__pclass у проекцію, щоб ця функція працювала.

"array"

Перетворює масив BSON або документ BSON на масив PHP. Не буде спеціальної обробки властивості __pclass[1], але його можна встановити, як елемент у масиві, що повертається, якщо він був присутній в документі BSON.

"object"или"stdClass"

Перетворює масив BSON або документ BSON на об'єкт stdClass. Не буде спеціальної обробки властивості __pclass[1], але вона може бути встановлена ​​як відкрита властивість у об'єкті, що повертається, якщо вона була присутня в документі BSON.

"bson"

Перетворює BSON масив на MongoDB\BSON\PackedArrayи BSON документ вMongoDB\BSON\Document, независимо от того, есть ли у BSON документа свойство__pclass[1]

Зауваження: Значениеbson доступне тільки для трьох кореневих типів, але не відображення для конкретних полів.

будь-який інший рядок

Визначає назву класу, який повинен десеріалізувати масив BSON або об'єкт BSON. Для об'єктів BSON, які містять властивості __pclass, цей клас матиме пріоритет.

Якщо названий клас не існує, не є конкретним (тобто абстрактним або інтерфейсом) або не реалізує MongoDB\BSON\Unserializable, то видається виняток MongoDB\Driver\Exception\InvalidArgumentException

Якщо об'єкт BSON має властивість __pclass, і цей клас існує та реалізує MongoDB\BSON\Persistable, він замінить клас, представлений у карті типів.

Свойства документа BSON,включаючисвойство__pclass, якщо воно існує, буде відправлено у вигляді асоціативного масиву в функцію MongoDB\BSON\Unserializable::bsonUnserialize() для ініціалізації властивостей об'єкта

TypeMaps

TypeMaps можно установить с помощью методаMongoDB\Driver\Cursor::setTypeMap() для об'єкту MongoDB\Driver\Cursorили аргумента$typeMapвMongoDB\BSON\toPHP() MongoDB\BSON\Document::toPHP() і MongoDB\BSON\PackedArray::toPHP(). Кожен із трьох класів (root document, иarray) може бути заданий індивідуально, на додаток до типів полів.

Якщо значення на карті дорівнює NULL, це означає те саме, що і значення за замовчуванням для цього елемента.

Приклади

У цих прикладах використовуються такі класи:

MyClass

Котрий не реалізує інтерфейс

YourClass

який реалізує MongoDB\BSON\Unserializable

OurClass

який реалізує MongoDB\BSON\Persistable

TheirClass

який розширює OurClass

МетодMongoDB\BSON\Unserializable::bsonUnserialize() класу YourClass, OurClass, OurClass виконує ітерацію за масивом та встановлює властивості без змін. Він такожустанавливает для свойства$unserializedзначение**true** :

Loading...

*typemap:[](все значения по умолчанию)*/ { "foo": "yes", "bar" : false } -> stdClass { $foo => 'yes', $bar => false }

{ "foo": "no", "array" : [ ] } -> stdClass { $foo => 'no', $array => [ ]

{ "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" : [ ] } -> [ "foo" => "no", "array" => [ ] ]

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