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 배열로 역직렬화됩니다.
  • __pclass 속성[1]이 없는 BSON 문서(루트 또는 포함)는 PHP stdClass 객체가 되며 각 BSON 문서 키가 공개 stdClass 속성으로 설정됩니다.
  • __pclass 속성[1]이 있는 BSON 문서(루트 또는 포함)는 __pclass 속성으로 정의된 클래스 이름의 PHP 객체가 됩니다.

    명명된 클래스가 MongoDB\BSON\Persistable 인터페이스를 구현하는 경우 __pclass 속성을 포함한 BSON 문서의 속성이 연관 배열로 MongoDB\BSON\Unserializable::bsonUnserialize() 함수에 전송되어 개체의 속성을 초기화합니다.

    명명된 클래스가 존재하지 않거나 MongoDB\BSON\Persistable 인터페이스를 구현하지 않는 경우 stdClass가 사용되며 각 BSON 문서 키(__pclass 포함)는 공개 stdClass 속성으로 설정됩니다.

    __pclass 기능은 검색된 MongoDB 문서의 일부인 속성에 의존합니다. 문서를 쿼리할 때 projection을 사용하는 경우 이 기능이 작동하려면 프로젝션에 __pclass 필드를 포함해야 합니다.

"array"
BSON 배열 또는 BSON 문서를 PHP 배열로 바꿉니다. __pclass 속성 [1]에 대한 특별한 처리는 없지만 BSON 문서에 있는 경우 반환된 배열의 요소로 설정될 수 있습니다.
"object" 또는 "stdClass"
BSON 배열 또는 BSON 문서를 stdClass 객체로 바꿉니다. __pclass 속성[1]에 대한 특별한 처리는 없지만 BSON 문서에 있는 경우 반환된 개체에서 공개 속성으로 설정될 수 있습니다.
any other string
BSON 배열 또는 BSON 개체가 역직렬화되어야 하는 클래스 이름을 정의합니다. __pclass 속성을 포함하는 BSON 객체의 경우 해당 클래스가 우선합니다.

명명된 클래스가 존재하지 않거나, 구체적이지 않거나(즉, 추상 또는 인터페이스), MongoDB\BSON\Unserializable을 구현하지 않으면 MongoDB\Driver\Exception\InvalidArgumentException 예외가 발생합니다.

BSON 객체에 __pclass 속성이 있고 해당 클래스가 존재하고 MongoDB\BSON\Persistable을 구현하는 경우 유형 맵에 제공된 클래스를 대체합니다.

존재하는 경우 __pclass 속성을 포함한 BSON 문서의 속성은 객체의 속성을 초기화하기 위해 MongoDB\BSON\Unserializable::bsonUnserialize() 함수에 연관 배열로 전송됩니다.


TypeMaps

TypeMaps는 MongoDB\Driver\Cursor 객체의 MongoDB\Driver\Cursor::setTypeMap() 메서드 또는 MongoDB\BSON\toPHP()$typeMap 인수를 통해 설정할 수 있습니다. 세 가지 클래스(루트, 문서 및 배열) 각각은 필드별 유형 외에도 개별적으로 설정할 수 있습니다.

맵의 값이 NULL이면 해당 항목의 기본값과 동일함을 의미합니다.


Examples

이 예제에서는 다음 클래스를 사용합니다.

MyClass
인터페이스를 구현하지 않는
YourClass
MongoDB\BSON\Unserializable을 구현하는
OurClass
MongoDB\BSON\Persistable을 구현하는
TheirClass
OurClass를 확장하는

YourClass, OurClass, TheyClass의 MongoDB\BSON\Unserializable::bsonUnserialize() 메서드는 배열을 반복하고 수정 없이 속성을 설정합니다. 또한 $unserialized 속성을 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") }