建模BSON数据
类型映射
大多数从MongoDB读取数据的方法都支持一个类型映射
选项,该选项允许控制BSON如何转换为PHP。此外,还有MongoDB\Client
、MongoDB\Database
和 MongoDB\Collection
类接受一个 typeMap
选项,该选项可以用于指定应用于任何支持的方法和所选类的默认类型映射(例如 MongoDB\Client::selectDatabase()
)。
MongoDB\Client
、MongoDB\Database
和 MongoDB\Collection
类默认使用以下类型映射
[ 'array' => 'MongoDB\Model\BSONArray', 'document' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument', ]
上述类型映射将分别将 BSON 文档和数组转换为 MongoDB\Model\BSONDocument
和 MongoDB\Model\BSONArray
对象。使用 root
和 document
键来区分顶层 BSON 文档和嵌入文档。
类型映射可以指定任何实现了MongoDB\BSON\Unserializable 以及 "array"
、"stdClass"
和 "object"
("stdClass"
和 "object"
是彼此的别名)的类。
可持久化类
The extension's persistence specification outlines how classes implementing its MongoDB\BSON\Persistable interface are serialized to and deserialized from BSON. The Persistable interface is analogous to PHP's Serializable interface.
该扩展自动处理实现 可持久化 接口类的序列化和反序列化,无需使用 typeMap
选项。这是通过在BSON文档中特殊属性中编码PHP类的名称来完成的。
注意
考虑以下类定义
class Person implements MongoDB\BSON\Persistable { private MongoDB\BSON\ObjectId $id; private string $name; private MongoDB\BSON\UTCDateTime $createdAt; public function __construct(string $name) { $this->id = new MongoDB\BSON\ObjectId; $this->name = $name; $this->createdAt = new MongoDB\BSON\UTCDateTime; } function bsonSerialize() { return [ '_id' => $this->id, 'name' => $this->name, 'createdAt' => $this->createdAt, ]; } function bsonUnserialize(array $data) { $this->id = $data['_id']; $this->name = $data['name']; $this->createdAt = $data['createdAt']; } }
以下示例创建了一个 Person
对象,将其插入数据库,并以相同类型的对象读取它
$collection = (new MongoDB\Client)->test->persons; $result = $collection->insertOne(new Person('Bob')); $person = $collection->findOne(['_id' => $result->getInsertedId()]); var_dump($person);
输出将类似于
object(Person)#18 (3) { ["id":"Person":private]=> object(MongoDB\BSON\ObjectId)#15 (1) { ["oid"]=> string(24) "56fad2c36118fd2e9820cfc1" } ["name":"Person":private]=> string(3) "Bob" ["createdAt":"Person":private]=> object(MongoDB\BSON\UTCDateTime)#17 (1) { ["milliseconds"]=> int(1459278531218) } }
在 MongoDB Shell 中,相同的文档可能显示为
{ "_id" : ObjectId("56fad2c36118fd2e9820cfc1"), "__pclass" : BinData(128,"UGVyc29u"), "name" : "Bob", "createdAt" : ISODate("2016-03-29T19:08:51.218Z") }
注意
MongoDB\BSON\Persistable 只能用于根和嵌套 BSON 文档。它不能用于 BSON 数组。
使用枚举
受支持的枚举可以与BSON一起使用,并将其序列化为它们的case值(即整数或字符串)。纯枚举没有受支持的case,不能直接序列化。这与json_encode().处理枚举的方式相似。
将后端枚举通过BSON进行往返操作需要特殊处理。以下示例中,包含枚举的类中的bsonUnserialize()
方法负责将值转换回枚举实例
enum Role: int { case USER = 1; case ADMIN = 2; } class User implements MongoDB\BSON\Persistable { public function __construct( private string $username, private Role $role, private MongoDB\BSON\ObjectId $_id = new MongoDB\BSON\ObjectId(), ) {} public function bsonSerialize(): array { return [ '_id' => $this->_id, 'username' => $this->username, 'role' => $this->role, ]; } public function bsonUnserialize(array $data): void { $this->_id = $data['_id']; $this->username = $data['username']; $this->role = Role::from($data['role']); } }
枚举不能实现MongoDB\BSON\Unserializable和MongoDB\BSON\Persistable接口,因为枚举实例没有状态,不能像普通对象那样实例化。然而,纯枚举和后端枚举可以实现MongoDB\BSON\Serializable接口,这可以用来克服后端枚举默认序列化为其实例值,而纯枚举不能序列化的行为。