PHP8 MongoDB BSON 的反序列化

2024-04-08 10:15 更新
警告

从技术上讲,BSON 文档可以包含重复的密钥,因为文档是 存储为键值对列表;但是,应用程序应避免 从生成具有重复键的文档作为服务器和驱动程序行为 可能未定义。由于 PHP 对象和数组不能有重复的键, 使用重复键解码 BSON 文档时,数据也可能丢失。

反序列化的旧扩展 BSON 文档和数组作为 PHP 数组。而 PHP 数组是 使用方便,这种行为是有问题的,因为不同的 BSON 类型可以反序列化为相同的 PHP 值(例如 和 ) 并制作它 无法推断出原始的BSON类型。默认情况下,当前驱动程序 通过确保 BSON 阵列和文档 分别转换为 PHP 数组和对象。mongo{"0": "foo"}["foo"]

对于复合类型,有三种数据类型:

指顶级 BSON 文档

公文

指嵌入式 BSON 文档

数组

指 BSON 数组

除了三种集合类型外,还可以配置 文档中的特定字段,以映射到下面提到的数据类型。 例如,以下类型映射允许您 将数组中的每个嵌入文档映射到 一个 Address 类和这些嵌入式地址文档中的每个字段 a 城市类:"addresses""city"

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

这三种数据类型中的每一种,以及特定于字段的映射, 可以针对不同的 PHP 类型进行映射。可能的映射值 是:

未设置或 NULL(默认值)
  • BSON 数组将被反序列化为 PHP 数组。

  • 没有 __pclass 属性的 BSON 文档(根文档或嵌入文档)[1]变成一个 PHP stdClass 对象,每个 BSON 文档密钥设置为公共 stdClass 属性。

  • 具有 __pclass 属性的 BSON 文档(根文档或嵌入文档)[1]成为 由 __pclass 属性定义的类名。

    如果命名类实现 MongoDB\BSON\Persistable 接口, 然后,BSON 文档的属性(包括 __pclass 属性)将作为关联发送 数组添加到 MongoDB\BSON\Unserializable::bsonUnserialize() 函数以初始化对象的属性。

    如果命名类不存在或未实现 MongoDB\BSON\Persistable 接口,则将使用 stdClass 和每个 BSON 文档 密钥(包括 __pclass)将设置为 public 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 对象应为的类名 反序列化为。对于包含__pclass属性的 BSON 对象,该类将采用 优先权。

如果命名的类不存在,则不是具体的(即它是 abstract 或接口),或者未实现 MongoDB\BSON\Unserializable,则会引发 MongoDB\Driver\Exception\InvalidArgumentException 异常。

如果 BSON 对象具有 __pclass 属性,并且 该类存在并实现 MongoDB\BSON\Persistable,它将 替换类型映射中提供的类。

将发送 BSON 文档的属性,包括 __pclass 属性(如果存在) 作为 MongoDB\BSON\Unserializable::bsonUnserialize() 函数的关联数组,用于初始化对象的属性。

字体图 

可以通过 MongoDB\Driver\Cursor 对象上的 MongoDB\Driver\Cursor::setTypeMap() 方法或 MongoDB\BSON\toPHP()、MongoDB\BSON\Document::toPHP() 和 MongoDB\BSON\PackedArray::toPHP() 的参数来设置 TypeMap。三者中的每一个 类(根、文档和数组)可以单独设置,此外 字段特定类型。$typeMap

如果映射中的值为 NULL,则表示与该项目的默认值相同。

例子

这些示例使用以下类:

我的班级

它不实现任何接口

你的班级

实现 MongoDB\BSON\Unserializable

我们的班级

实现 MongoDB\BSON\Persistable

TheirClass

它扩展了 OurClass

YourClass、OurClass、TheirClass 的 MongoDB\BSON\Unserializable::bsonUnserialize() 方法遍历数组并设置 未经修改的属性。它还设置了 属性为 true:$unserialized

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


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号