From 1123fab54b867f9102a43109579f7bbda77deb18 Mon Sep 17 00:00:00 2001 From: norareidy Date: Tue, 3 Jun 2025 13:48:20 -0400 Subject: [PATCH 1/5] DOCSP-47059: Work with BSON --- source/data-formats/modeling-bson-data.txt | 370 ++++++++++++--------- source/includes/bson.php | 109 ++++++ 2 files changed, 322 insertions(+), 157 deletions(-) create mode 100644 source/includes/bson.php diff --git a/source/data-formats/modeling-bson-data.txt b/source/data-formats/modeling-bson-data.txt index 144790db..3922bec1 100644 --- a/source/data-formats/modeling-bson-data.txt +++ b/source/data-formats/modeling-bson-data.txt @@ -1,8 +1,8 @@ .. _php-bson: -================== -Modeling BSON Data -================== +=================== +Work with BSON Data +=================== .. contents:: On this page @@ -11,140 +11,199 @@ Modeling BSON Data :depth: 2 :class: singlecol -.. _php-type-map: +Overview +-------- -Type Maps ---------- +In this guide, you can learn how to create and interact with BSON documents +by using the {+driver-short+}. -Most methods that read data from MongoDB support a ``typeMap`` option, which -allows control over how BSON is converted to PHP. Additionally, -the :phpclass:`MongoDB\Client`, :phpclass:`MongoDB\Database`, and -:phpclass:`MongoDB\Collection` classes accept a ``typeMap`` option, which can -be used to specify a default type map to apply to any supporting methods and -selected classes (e.g. :phpmethod:`MongoDB\Client::getDatabase()`). +**BSON**, or Binary JSON, is the data format that MongoDB uses to organize +and store data. This data format includes all JSON data structure types and +supports additional types, including dates, different-sized integers, ``ObjectId`` +values, and binary data. The {+library-short+} provides the ``MongoDB\Model\BSONArray`` +and ``MongoDB\Model\BSONDocument`` types to store BSON data. -The :phpclass:`MongoDB\Client`, :phpclass:`MongoDB\Database`, and -:phpclass:`MongoDB\Collection` classes use the following type map by -default: +.. tip:: -.. code-block:: php + For a complete list of supported BSON types, see :manual:`BSON Types + ` in the {+mdb-server+} manual. - [ - 'array' => 'MongoDB\Model\BSONArray', - 'document' => 'MongoDB\Model\BSONDocument', - 'root' => 'MongoDB\Model\BSONDocument', - ] +.. _php-bson-sample: -The type map above will convert BSON documents and arrays to -:phpclass:`MongoDB\Model\BSONDocument` and -:phpclass:`MongoDB\Model\BSONArray` objects, respectively. The ``root`` and -``document`` keys are used to distinguish the top-level BSON document from -embedded documents, respectively. +Sample Data +~~~~~~~~~~~ -A type map may specify any class that implements -:php:`MongoDB\BSON\Unserializable ` as well as -``"array"``, ``"stdClass``", and ``"object"`` (``"stdClass``" and ``"object"`` -are aliases of one another). +The code examples in this guide reference the following sample BSON document: -.. seealso:: +.. code-block:: js - :php:`Deserialization from BSON ` in the PHP manual + { + "address" : { + "street" : "Pizza St", + "zipcode" : "10003" + }, + "coord" : [-73.982419, 41.579505] + "cuisine" : "Pizza", + "name" : "Mongo's Pizza" + } +Create a BSON Document +---------------------- -Persistable Classes -------------------- +You can create a BSON document by using the same notation you use to create an +associative array in {+language+}. The {+library-short+} automatically converts +{+language+} arrays into BSON documents when inserting them into a collection. -The extension's :php:`persistence specification ` outlines -how classes implementing its :php:`MongoDB\BSON\Persistable -` interface are serialized to and deserialized from -BSON. The :php:`Persistable ` interface is analogous -to PHP's :php:`Serializable interface `. +The following example creates a BSON document that represents the preceding +:ref:`sample BSON document `: -The extension automatically handles serialization and deserialization for -classes implementing the :php:`Persistable ` interface -without requiring the use of the ``typeMap`` option. This is done by encoding -the name of the PHP class in a special property within the BSON document. +.. literalinclude:: /includes/bson.php + :language: php + :dedent: + :start-after: start-create-doc + :end-before: end-create-doc -.. note:: +Change a BSON Document +---------------------- - When deserializing a PHP variable from BSON, the encoded class name of a - :php:`Persistable ` object will override any class - specified in the type map, but it will not override ``"array"`` and - ``"stdClass"`` or ``"object"``. This is discussed in the - :php:`persistence specification ` but it bears - repeating. +You can modify the contents of a BSON document by using the same notation you use to +modify an associative array in {+language+}. This example makes the following changes +to the :ref:`sample BSON document `: -Consider the following class definition: +- Adds a new ``restaurant_id`` field that has a value of ``12345`` +- Removes the ``cuisine`` field +- Sets the value of the ``name`` field to ``"Mongo's Pizza Place"`` -.. code-block:: php +.. literalinclude:: /includes/bson.php + :language: php + :dedent: + :start-after: start-modify-doc + :end-before: end-modify-doc - 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']; - } - } +The following sections describe how to configure your application's +serialization of BSON data: -The following example constructs a ``Person`` object, inserts it into the -database, and reads it back as an object of the same type: +- :ref:`php-type-map`: Use the ``typeMap`` option to specify the default conversion + between {+language+} types and BSON types + +- :ref:`php-persistable-classes`: Use the ``MongoDB\BSON\Persistable`` interface to + enable serialization + +- :ref:`php-enums`: Use the ``bsonSerialize()`` and ``bsonUnserialize()`` methods to + specify serialization between backed enums and BSON values + +.. _php-type-map: + +Type Maps +~~~~~~~~~ + +You can set the ``typeMap`` option, which configures how BSON values are converted to +{+language+} values, at the following levels: + +- ``MongoDB\Client``, which sets the *default for all operations* unless overridden +- ``MongoDB\Database`` +- ``MongoDB\Collection`` + +This list also indicates the increasing order of precedence of the option settings. For +example, if you set a ``typeMap`` for a collection, it will override the type map +set on the database. + +The {+library-short+} uses the following type map by default: .. code-block:: php - 'MongoDB\Model\BSONArray', + 'document' => 'MongoDB\Model\BSONDocument', + 'root' => 'MongoDB\Model\BSONDocument', + ] - $collection = (new MongoDB\Client)->test->persons; +This type map performs the following conversions: - $result = $collection->insertOne(new Person('Bob')); +- Arrays to ``MongoDB\Model\BSONArray`` objects +- Top-level and embedded BSON documents to ``MongoDB\Model\BSONDocument`` objects - $person = $collection->findOne(['_id' => $result->getInsertedId()]); +A type map can specify any class that implements +:php:`MongoDB\BSON\Unserializable `, as well as +the ``array``, ``stdClass``, and ``object`` types. - var_dump($person); +Custom Type Map Example +``````````````````````` -The output would then resemble: +The following example sets the ``typeMap`` option for the ``restaurants`` collection +that serializes arrays and BSON documents as ``MongoDB\Model\BSONDocument`` objects: -.. code-block:: none +.. literalinclude:: /includes/bson.php + :language: php + :dedent: + :start-after: start-type-map + :end-before: end-type-map - 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) - } - } +.. _php-persistable-classes: + +Persistable Classes +~~~~~~~~~~~~~~~~~~~ + +You can create classes that implement the ``MongoDB\BSON\Persistable`` interface, +which instructs the {+library-short+} to automatically perform serialization and +deserialization according to the {+extension-short+}'s :php:`persistence specification +`. The ``Persistable`` interface is analogous to {+language+}'s +:php:`Serializable interface `. + +When deserializing a PHP variable from BSON, the encoded class name of a +``Persistable`` object overrides any class specified in the ``typeMap`` option. +However, it does not override ``array``, ``stdClass``, or ``object`` types. -The same document in the MongoDB shell might display as: +.. tip:: + + To learn more about the ``Persistable`` interface, see :php:`Persistable ` + in the {+extension-short+} documentation. + +Example +``````` + +Consider the following ``Person`` class definition: + +.. literalinclude:: /includes/bson.php + :language: php + :dedent: + :start-after: start-person-class + :end-before: end-person-class + +The following example constructs a ``Person`` object, inserts it into the +database, and reads it back as an object of the same type: + +.. io-code-block:: + :copyable: + + .. input:: /includes/bson.php + :start-after: start-person-serialize + :end-before: end-person-serialize + :language: php + :dedent: + + .. output:: + :visible: false + + 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) + } + } + +The returned document is equivalent to the following BSON document: .. code-block:: js @@ -157,62 +216,59 @@ The same document in the MongoDB shell might display as: .. note:: - :php:`MongoDB\BSON\Persistable ` may only be used - for root and embedded BSON documents. It may not be used for BSON arrays. + You can use the ``Persistable`` interface for root and embedded BSON documents + only, not BSON arrays. -Working with Enums ------------------- +.. _php-enums: -:php:`Backed enums ` can be used with BSON and will -serialize as their case value (i.e. integer or string). -:php:`Pure enums `, which have no backed cases, cannot be -directly serialized. This is similar to how enums are handled by -:php:`json_encode() `. +Enum Values +~~~~~~~~~~~ -Round-tripping a backed enum through BSON requires special handling. In the -following example, the ``bsonUnserialize()`` method in the class containing the -enum is responsible for converting the value back to an enum case: +You can serialize and deserialize backed enums into BSON data. Backed +enum values serialize as their case value, while pure enums without +case values cannot be directly serialized. To perform these conversions, +you must specify serialization logic by defining the ``bsonSerialize()`` +and ``bsonUnserialize()`` methods. -.. code-block:: php +.. tip:: - ` + in the {+extension-short+} documentation. - enum Role: int - { - case USER = 1; - case ADMIN = 2; - } +Example +``````` - 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']); - } - } +The following example specifies logic for serializing and deserializing the +``Role`` enum by defining the ``bsonSerialize()`` and ``bsonUnserialize()`` +methods: + +.. literalinclude:: /includes/bson.php + :language: php + :dedent: + :start-after: start-backed-enum + :end-before: end-backed-enum + +.. note:: + + Enums cannot implement the ``MongoDB\BSON\Unserializable`` and + ``MongoDB\BSON\Persistable`` interfaces, since enum cases have no + state and cannot be instantiated like class objects. However, pure and backed + enums can implement ``MongoDB\BSON\Serializable``, which you can use to + override the default enum serialization behavior. + +API Documentation +----------------- + +To learn more about any of the methods or types discussed in this +guide, see the following library API documentation: + +- :phpmethod:`MongoDB\Database::createCollection()` +- :phpclass:`MongoDB\Model\BSONDocument` +- :phpclass:`MongoDB\Model\BSONArray` + +To learn more about the {+extension-short+} types discussed in this +guide, see the following extension API documentation: -Enums are prohibited from implementing -:php:`MongoDB\BSON\Unserializable ` and -:php:`MongoDB\BSON\Persistable `, since enum cases -have no state and cannot be instantiated like ordinary objects. Pure and backed -enums can, however, implement -:php:`MongoDB\BSON\Serializable `, which can be -used to overcome the default behavior whereby backed enums are serialized as -their case value and pure enums cannot be serialized. +- :php:`MongoDB\BSON\Persistable ` +- :php:`MongoDB\BSON\Unserializable ` +- :php:`MongoDB\BSON\Serializable ` diff --git a/source/includes/bson.php b/source/includes/bson.php new file mode 100644 index 00000000..9cc9d9e2 --- /dev/null +++ b/source/includes/bson.php @@ -0,0 +1,109 @@ + [ + 'street' => 'Pizza St', + 'zipcode' => '10003' + ], + 'coord' => [-73.982419, 41.579505], + 'cuisine' => 'Pizza', + 'name' => 'Mongo\'s Pizza' +]; +// end-create-doc + +// start-modify-doc +$document['restaurant_id'] = 12345; +unset($document['cuisine']); +$document['name'] = 'Mongo\'s Pizza Place'; +// end-modify-doc + +// start-type-map +$options = [ + 'typeMap' => [ + 'array' => 'MongoDB\Model\BSONDocument', + 'root' => 'MongoDB\Model\BSONDocument', + 'document' => 'MongoDB\Model\BSONDocument' + ] +]; + +$db->createCollection('restaurants', $options); +// end-type-map + +// start-person-class +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']; + } +} +// end-person-class + +// start-person-serialize +$collection = $client->test->persons; +$result = $collection->insertOne(new Person('Bob')); +$person = $collection->findOne(['_id' => $result->getInsertedId()]); + +var_dump($person); +// end-person-serialize + +// start-backed-enum +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']); + } +} +// end-backed-enum \ No newline at end of file From 222cf2ab97cd45fd22cb645f167ac2811ba5ffc8 Mon Sep 17 00:00:00 2001 From: norareidy Date: Tue, 3 Jun 2025 13:59:07 -0400 Subject: [PATCH 2/5] edits --- source/data-formats/modeling-bson-data.txt | 9 ++++----- source/includes/bson.php | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/source/data-formats/modeling-bson-data.txt b/source/data-formats/modeling-bson-data.txt index 3922bec1..6821dc4d 100644 --- a/source/data-formats/modeling-bson-data.txt +++ b/source/data-formats/modeling-bson-data.txt @@ -52,7 +52,7 @@ Create a BSON Document You can create a BSON document by using the same notation you use to create an associative array in {+language+}. The {+library-short+} automatically converts -{+language+} arrays into BSON documents when inserting them into a collection. +these values into BSON documents when inserting them into a collection. The following example creates a BSON document that represents the preceding :ref:`sample BSON document `: @@ -71,7 +71,6 @@ modify an associative array in {+language+}. This example makes the following ch to the :ref:`sample BSON document `: - Adds a new ``restaurant_id`` field that has a value of ``12345`` -- Removes the ``cuisine`` field - Sets the value of the ``name`` field to ``"Mongo's Pizza Place"`` .. literalinclude:: /includes/bson.php @@ -127,8 +126,8 @@ This type map performs the following conversions: - Top-level and embedded BSON documents to ``MongoDB\Model\BSONDocument`` objects A type map can specify any class that implements -:php:`MongoDB\BSON\Unserializable `, as well as -the ``array``, ``stdClass``, and ``object`` types. +:php:`MongoDB\BSON\Unserializable `. It can +also specify the ``array``, ``stdClass``, and ``object`` types. Custom Type Map Example ``````````````````````` @@ -259,7 +258,7 @@ methods: API Documentation ----------------- -To learn more about any of the methods or types discussed in this +To learn more about any of the {+library-short+} methods or types discussed in this guide, see the following library API documentation: - :phpmethod:`MongoDB\Database::createCollection()` diff --git a/source/includes/bson.php b/source/includes/bson.php index 9cc9d9e2..72d0f96e 100644 --- a/source/includes/bson.php +++ b/source/includes/bson.php @@ -4,6 +4,7 @@ $uri = getenv('MONGODB_URI') ?: throw new RuntimeException('Set the MONGODB_URI variable to your Atlas URI that connects to the sample dataset'); $client = new MongoDB\Client($uri); +$db = $client->test; // start-create-doc $document = [ @@ -19,7 +20,6 @@ // start-modify-doc $document['restaurant_id'] = 12345; -unset($document['cuisine']); $document['name'] = 'Mongo\'s Pizza Place'; // end-modify-doc From 4dbde4283797b79f8ab94d455ee763fb87b1b023 Mon Sep 17 00:00:00 2001 From: norareidy Date: Thu, 5 Jun 2025 10:49:12 -0400 Subject: [PATCH 3/5] RR feedback --- source/data-formats/modeling-bson-data.txt | 71 ++++++++++++---------- source/includes/bson.php | 4 +- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/source/data-formats/modeling-bson-data.txt b/source/data-formats/modeling-bson-data.txt index 6821dc4d..154e1443 100644 --- a/source/data-formats/modeling-bson-data.txt +++ b/source/data-formats/modeling-bson-data.txt @@ -15,17 +15,17 @@ Overview -------- In this guide, you can learn how to create and interact with BSON documents -by using the {+driver-short+}. +by using the {+library-short+}. **BSON**, or Binary JSON, is the data format that MongoDB uses to organize and store data. This data format includes all JSON data structure types and -supports additional types, including dates, different-sized integers, ``ObjectId`` -values, and binary data. The {+library-short+} provides the ``MongoDB\Model\BSONArray`` -and ``MongoDB\Model\BSONDocument`` types to store BSON data. +also supports other types, including dates, different-sized integers, ``ObjectId`` +values, and binary data. The {+library-short+} provides the :phpclass:`MongoDB\Model\BSONArray` +and :phpclass:`MongoDB\Model\BSONDocument` types to store BSON data. .. tip:: - For a complete list of supported BSON types, see :manual:`BSON Types + To view a complete list of supported BSON types, see :manual:`BSON Types ` in the {+mdb-server+} manual. .. _php-bson-sample: @@ -44,13 +44,13 @@ The code examples in this guide reference the following sample BSON document: }, "coord" : [-73.982419, 41.579505] "cuisine" : "Pizza", - "name" : "Mongo's Pizza" + "name" : "Planet Pizza" } Create a BSON Document ---------------------- -You can create a BSON document by using the same notation you use to create an +You can create a BSON document by using the same notation that you use to create an associative array in {+language+}. The {+library-short+} automatically converts these values into BSON documents when inserting them into a collection. @@ -66,12 +66,12 @@ The following example creates a BSON document that represents the preceding Change a BSON Document ---------------------- -You can modify the contents of a BSON document by using the same notation you use to +You can modify the contents of a BSON document by using the same notation that you use to modify an associative array in {+language+}. This example makes the following changes to the :ref:`sample BSON document `: - Adds a new ``restaurant_id`` field that has a value of ``12345`` -- Sets the value of the ``name`` field to ``"Mongo's Pizza Place"`` +- Changes the ``name`` field value to ``"Galaxy Pizza"`` .. literalinclude:: /includes/bson.php :language: php @@ -79,6 +79,13 @@ to the :ref:`sample BSON document `: :start-after: start-modify-doc :end-before: end-modify-doc +.. note:: + + The preceding code changes only the in-memory values of the sample BSON + document. It does not run any database operations that change values stored + in MongoDB. To learn how to modify documents stored in MongoDB, see the + :ref:`php-write-update` guide. + Customize BSON Serialization ---------------------------- @@ -86,21 +93,21 @@ The following sections describe how to configure your application's serialization of BSON data: - :ref:`php-type-map`: Use the ``typeMap`` option to specify the default conversion - between {+language+} types and BSON types + between {+language+} types and BSON types. - :ref:`php-persistable-classes`: Use the ``MongoDB\BSON\Persistable`` interface to - enable serialization + enable serialization. - :ref:`php-enums`: Use the ``bsonSerialize()`` and ``bsonUnserialize()`` methods to - specify serialization between backed enums and BSON values + specify serialization between backed enums and BSON values. .. _php-type-map: Type Maps ~~~~~~~~~ -You can set the ``typeMap`` option, which configures how BSON values are converted to -{+language+} values, at the following levels: +You can set the ``typeMap`` option, which configures serialization and +deserialization between {+language+} and BSON values, at the following levels: - ``MongoDB\Client``, which sets the *default for all operations* unless overridden - ``MongoDB\Database`` @@ -120,14 +127,14 @@ The {+library-short+} uses the following type map by default: 'root' => 'MongoDB\Model\BSONDocument', ] -This type map performs the following conversions: +This type map performs the following conversions in both directions: - Arrays to ``MongoDB\Model\BSONArray`` objects - Top-level and embedded BSON documents to ``MongoDB\Model\BSONDocument`` objects -A type map can specify any class that implements -:php:`MongoDB\BSON\Unserializable `. It can -also specify the ``array``, ``stdClass``, and ``object`` types. +A type map can specify any class that implements the +:php:`MongoDB\BSON\Unserializable ` interface. +It can also specify conversions of the ``array``, ``stdClass``, and ``object`` types. Custom Type Map Example ``````````````````````` @@ -146,25 +153,22 @@ that serializes arrays and BSON documents as ``MongoDB\Model\BSONDocument`` obje Persistable Classes ~~~~~~~~~~~~~~~~~~~ -You can create classes that implement the ``MongoDB\BSON\Persistable`` interface, -which instructs the {+library-short+} to automatically perform serialization and -deserialization according to the {+extension-short+}'s :php:`persistence specification -`. The ``Persistable`` interface is analogous to {+language+}'s -:php:`Serializable interface `. +You can create classes that implement the :php:`MongoDB\BSON\Persistable ` +interface. This interface instructs the {+library-short+} to automatically perform serialization +and deserialization according to the {+extension-short+}'s :php:`persistence specification +` without requiring the ``typeMap`` option. The ``Persistable`` interface +is analogous to {+language+}'s :php:`Serializable interface `. When deserializing a PHP variable from BSON, the encoded class name of a ``Persistable`` object overrides any class specified in the ``typeMap`` option. However, it does not override ``array``, ``stdClass``, or ``object`` types. -.. tip:: - - To learn more about the ``Persistable`` interface, see :php:`Persistable ` - in the {+extension-short+} documentation. - Example ``````` -Consider the following ``Person`` class definition: +Consider the following ``Person`` class definition, which implements the +``Persistable`` interface and specifies how to serialize and deserialize +object fields as BSON values: .. literalinclude:: /includes/bson.php :language: php @@ -213,6 +217,10 @@ The returned document is equivalent to the following BSON document: "createdAt" : ISODate("2016-03-29T19:08:51.218Z") } +The {+library-short+} automatically adds the ``__pclass`` field to keep +track of the document's corresponding class name, which allows you to +deserialize the document into a ``Person`` object. + .. note:: You can use the ``Persistable`` interface for root and embedded BSON documents @@ -227,7 +235,7 @@ You can serialize and deserialize backed enums into BSON data. Backed enum values serialize as their case value, while pure enums without case values cannot be directly serialized. To perform these conversions, you must specify serialization logic by defining the ``bsonSerialize()`` -and ``bsonUnserialize()`` methods. +and ``bsonUnserialize()`` methods in your class definition. .. tip:: @@ -243,6 +251,7 @@ methods: .. literalinclude:: /includes/bson.php :language: php + :emphasize-lines: 15, 24 :dedent: :start-after: start-backed-enum :end-before: end-backed-enum @@ -250,7 +259,7 @@ methods: .. note:: Enums cannot implement the ``MongoDB\BSON\Unserializable`` and - ``MongoDB\BSON\Persistable`` interfaces, since enum cases have no + ``MongoDB\BSON\Persistable`` interfaces because enum cases have no state and cannot be instantiated like class objects. However, pure and backed enums can implement ``MongoDB\BSON\Serializable``, which you can use to override the default enum serialization behavior. diff --git a/source/includes/bson.php b/source/includes/bson.php index 72d0f96e..99cacce4 100644 --- a/source/includes/bson.php +++ b/source/includes/bson.php @@ -14,13 +14,13 @@ ], 'coord' => [-73.982419, 41.579505], 'cuisine' => 'Pizza', - 'name' => 'Mongo\'s Pizza' + 'name' => 'Planet Pizza' ]; // end-create-doc // start-modify-doc $document['restaurant_id'] = 12345; -$document['name'] = 'Mongo\'s Pizza Place'; +$document['name'] = 'Galaxy Pizza'; // end-modify-doc // start-type-map From d2dcac9d2fa5f9b44add9f4b0f6ad603ab2b3210 Mon Sep 17 00:00:00 2001 From: norareidy Date: Thu, 5 Jun 2025 11:04:05 -0400 Subject: [PATCH 4/5] enum ex --- source/data-formats/modeling-bson-data.txt | 33 ++++++++++++++++++++-- source/includes/bson.php | 10 ++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/source/data-formats/modeling-bson-data.txt b/source/data-formats/modeling-bson-data.txt index 154e1443..7461cbbb 100644 --- a/source/data-formats/modeling-bson-data.txt +++ b/source/data-formats/modeling-bson-data.txt @@ -245,9 +245,9 @@ and ``bsonUnserialize()`` methods in your class definition. Example ``````` -The following example specifies logic for serializing and deserializing the -``Role`` enum by defining the ``bsonSerialize()`` and ``bsonUnserialize()`` -methods: +Consider the following ``User`` class definition, which specifies +logic for serializing and deserializing its fields into BSON values. +The class includes a ``role`` field, which has a backed enum value: .. literalinclude:: /includes/bson.php :language: php @@ -256,6 +256,33 @@ methods: :start-after: start-backed-enum :end-before: end-backed-enum +The following example constructs a ``User`` object with a ``role`` field, +inserts it into the database, and reads it back as an object of the same type: + +.. io-code-block:: + :copyable: + + .. input:: /includes/bson.php + :start-after: start-enum-serialize + :end-before: end-enum-serialize + :language: php + :dedent: + + .. output:: + :visible: false + + 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) "..." + } + } + .. note:: Enums cannot implement the ``MongoDB\BSON\Unserializable`` and diff --git a/source/includes/bson.php b/source/includes/bson.php index 99cacce4..cb2a510d 100644 --- a/source/includes/bson.php +++ b/source/includes/bson.php @@ -106,4 +106,12 @@ public function bsonUnserialize(array $data): void $this->role = Role::from($data['role']); } } -// end-backed-enum \ No newline at end of file +// end-backed-enum + +// start-enum-serialize +$collection = $client->test->users; +$result = $collection->insertOne(new User('alice', Role::USER)); +$person = $collection->findOne(['_id' => $result->getInsertedId()]); + +var_dump($person); +// end-enum-serialize \ No newline at end of file From 36ac8c3a272f6de01da2146d825062eb055dea13 Mon Sep 17 00:00:00 2001 From: norareidy Date: Thu, 5 Jun 2025 13:49:51 -0400 Subject: [PATCH 5/5] feedback --- source/data-formats/modeling-bson-data.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/data-formats/modeling-bson-data.txt b/source/data-formats/modeling-bson-data.txt index 7461cbbb..44257396 100644 --- a/source/data-formats/modeling-bson-data.txt +++ b/source/data-formats/modeling-bson-data.txt @@ -89,8 +89,8 @@ to the :ref:`sample BSON document `: Customize BSON Serialization ---------------------------- -The following sections describe how to configure your application's -serialization of BSON data: +The following sections describe how to configure the way your application +serializes BSON data: - :ref:`php-type-map`: Use the ``typeMap`` option to specify the default conversion between {+language+} types and BSON types.