Overview
在本指南中,您可以学习;了解如何使用PHP库创建BSON文档并与之交互。
BSON (即 Binary JSON)是MongoDB用于组织和存储数据的数据格式。这种数据格式包括所有JSON数据结构类型,还支持其他类型,包括日期、不同大小的整数、ObjectId
值和二进制数据。PHP库提供了 MongoDB\Model\BSONArray
和 MongoDB\Model\BSONDocument
类型来存储BSON数据。
提示
要查看支持的BSON 类型的完整列表,请参阅MongoDB Server手册中的 BSON 类型。
样本数据
本指南中的代码示例引用了以下示例BSON文档:
{ "address" : { "street" : "Pizza St", "zipcode" : "10003" }, "coord" : [-73.982419, 41.579505] "cuisine" : "Pizza", "name" : "Planet Pizza" }
创建 BSON 文档
您可以使用与在PHP中创建关联大量相同的符号来创建BSON文档。将这些值插入集合时, PHP库会自动将这些值转换为BSON文档。
以下示例创建一个BSON文档来表示前面的示例BSON文档:
$document = [ 'address' => [ 'street' => 'Pizza St', 'zipcode' => '10003', ], 'coord' => [-73.982419, 41.579505], 'cuisine' => 'Pizza', 'name' => 'Planet Pizza', ];
更改 BSON 文档
您可以使用与PHP中修改关联大量相同的表示法来修改BSON文档的内容。此示例对示例BSON文档:进行了以下更改:
添加值为
12345
的新restaurant_id
字段将
name
字段值更改为"Galaxy Pizza"
$document['restaurant_id'] = 12345; $document['name'] = 'Galaxy Pizza';
注意
前面的代码仅更改示例BSON文档在内存中的值。它不会运行任何会更改MongoDB中存储的值的数据库操作。要学习;了解如何修改存储在MongoDB中的文档,请参阅更新文档指南。
自定义BSON序列化
以下部分介绍如何配置应用程序序列化BSON数据的方式:
类型映射:使用
typeMap
选项指定PHP类型和BSON 类型之间的默认转换。持久化类:使用
MongoDB\BSON\Persistable
接口启用序列化。枚举值:使用
bsonSerialize()
和bsonUnserialize()
方法指定支持的枚举与BSON值之间的序列化。
类型映射
您可以在以下级别设立typeMap
选项,该选项在PHP和BSON值之间配置序列化和反序列化:
MongoDB\Client
,这将为所有操作设置默认,除非被覆盖MongoDB\Database
MongoDB\Collection
此列表还指示了选项设置的优先级递增顺序。示例,如果为集合设立typeMap
,它将覆盖数据库上设立的类型映射。
PHP库默认使用以下类型映射:
[ 'array' => 'MongoDB\Model\BSONArray', 'document' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument', ]
此类型映射在两个方向上执行以下转换:
数组到
MongoDB\Model\BSONArray
对象顶级和嵌入式BSON文档到
MongoDB\Model\BSONDocument
对象
类型映射可以指定任何实现MongoDB\ BSON\Unserializable 接口的类。它还可以指定array
、stdClass
和object
类型的转换。
自定义类型映射示例
以下示例为将数组和BSON文档序列化为 MongoDB\Model\BSONDocument
对象的 restaurants
集合设置 typeMap
选项:
$options = [ 'typeMap' => [ 'array' => 'MongoDB\Model\BSONDocument', 'root' => 'MongoDB\Model\BSONDocument', 'document' => 'MongoDB\Model\BSONDocument', ], ]; $db->createCollection('restaurants', $options);
可持久化类
您可以创建实现MongoDB\ BSON\Persistable 接口的类。此接口指示PHP库根据PHP扩展的持久性规范自动执行序列化和反序列化,而无需使用 选项。 typeMap
Persistable
接口类似于 PHP 的 Serializable 接口。
从BSON反序列化PHP变量时,Persistable
对象的编码类名会覆盖 typeMap
选项中指定的任何类。但是,它不会覆盖 array
、stdClass
或 object
类型。
例子
考虑以下 Person
类定义,它实现了 Persistable
接口并指定了如何将对象字段序列化和反序列化为BSON值:
class Person implements MongoDB\BSON\Persistable { private \MongoDB\BSON\ObjectId $id; private \MongoDB\BSON\UTCDateTime $createdAt; public function __construct(private string $name) { $this->id = new \MongoDB\BSON\ObjectId(); $this->createdAt = new \MongoDB\BSON\UTCDateTime(); } public function bsonSerialize(): array { return [ '_id' => $this->id, 'name' => $this->name, 'createdAt' => $this->createdAt, ]; } public function bsonUnserialize(array $data): void { $this->id = $data['_id']; $this->name = $data['name']; $this->createdAt = $data['createdAt']; } }
以下示例构造一个Person
对象,将其插入数据库,然后将其作为相同类型的对象读回:
$collection = $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) } }
返回的文档相当于以下BSON文档:
{ "_id" : ObjectId("56fad2c36118fd2e9820cfc1"), "__pclass" : BinData(128,"UGVyc29u"), "name" : "Bob", "createdAt" : ISODate("2016-03-29T19:08:51.218Z") }
PHP库自动添加 __pclass
字段来追踪文档相应的类名,这样您就可以将文档反序列化为 Person
对象。
注意
您只能将 Persistable
接口用于根文档和嵌入式BSON文档,而不能用于BSON数组。
Enum Values
您可以将支持的枚举序列化和反序列化为BSON数据。支持的枚举值会序列化为其大小写值,而没有大小写值的纯枚举无法直接序列化。要执行这些转换,您必须通过在类定义中定义 bsonSerialize()
和 bsonUnserialize()
方法来指定序列化逻辑。
例子
考虑以下名为 Role
的支持枚举,它有两个整数值的情况:
enum Role: int { case USER = 1; case ADMIN = 2; }
此 User
类定义包括一个具有 Role
枚举值的 role
字段,并指定将其字段序列化和反序列化为BSON值的逻辑:
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']); } }
以下示例构造一个带有 role
字段的 User
对象,将其插入数据库,并将其作为相同类型的对象读回:
$collection = $client->test->users; $result = $collection->insertOne(new User('alice', Role::USER)); $person = $collection->findOne(['_id' => $result->getInsertedId()]); var_dump($person);
object(User)#40 (3) { ["username":"User":private]=> string(5) "alice" ["role":"User":private]=> enum(Role::USER) ["_id":"User":private]=> object(MongoDB\BSON\ObjectId)#38 (1) { ["oid"]=> string(24) "..." } }
注意
枚举无法实现MongoDB\BSON\Unserializable
和 MongoDB\BSON\Persistable
接口,因为枚举没有状态,也无法像类对象一样进行实例化。但是,纯枚举和支持枚举可以实现MongoDB\BSON\Serializable
,您可以使用它来覆盖默认的枚举序列化行为。
API 文档
要进一步学习;了解本指南中讨论的PHP库方法或类型,请参阅以下库API文档:
要学习;了解有关本指南中讨论的PHP扩展类型的更多信息,请参阅以下扩展API文档: