@@ -16,31 +16,27 @@ Overview
16
16
--------
17
17
18
18
Codecs are used to decode BSON documents into PHP objects, and encode PHP objects into BSON documents. In contrast to
19
- other methods, they allow for more flexibility and customization of the process and how different data types are
20
- handled. They allow separating the logic for BSON encoding and decoding from the domain classes, allowing to decode BSON
21
- into plain old PHP objects (POPOs).
19
+ other methods (e.g. type maps), codecs allow for greater customization and handling of different data types. They allow
20
+ separating the logic for BSON encoding and decoding from the domain classes, allowing to decode BSON into plain old PHP
21
+ objects (POPOs).
22
22
23
- Document Codec Usage
24
- --------------------
23
+ Handling Documents
24
+ ------------------
25
25
26
26
The main logic is contained in a document codec. This class implements the ``MongoDB\Codec\DocumentCodec`` interface and
27
27
defines what data types can be encoded/decoded and how. The following example defines a ``Person`` class and a codec to
28
- encode/decode it:
28
+ transform it:
29
29
30
30
.. code-block:: php
31
31
32
32
<?php
33
33
34
34
final class Person
35
35
{
36
- public MongoDB\BSON\ObjectId $id;
37
- public string $name;
38
-
39
- public function __construct(string $name)
40
- {
41
- $this->id = new MongoDB\BSON\ObjectId();
42
- $this->name = $name;
43
- }
36
+ public function __construct(
37
+ public string $name,
38
+ public readonly MongoDB\BSON\ObjectId $id = new MongoDB\BSON\ObjectId(),
39
+ ) {}
44
40
}
45
41
46
42
.. code-block:: php
@@ -69,10 +65,10 @@ encode/decode it:
69
65
throw UnsupportedValueException::invalidDecodableValue($value);
70
66
}
71
67
72
- $person = new Person($value->get('name'));
73
- $person->id = $value->get('_id');
74
-
75
- return $person ;
68
+ return new Person(
69
+ $value->get('name'),
70
+ $value->get('_id'),
71
+ ) ;
76
72
}
77
73
78
74
public function encode($value): MongoDB\BSON\Document
@@ -105,19 +101,21 @@ To then use this codec with a collection, specify the ``codec`` option when sele
105
101
$person = $collection->findOne();
106
102
107
103
The example above selects a collection and instructs it to use the ``PersonCodec`` for encoding and decoding documents.
108
- When inserting data, the ``PersonCodec`` is used to encode the document. When retrieving data, the ``PersonCodec`` is
109
- used to decode BSON data into a ``Person`` instance. Note that while the ``PersonCodec`` could technically decode any
104
+ When inserting data, the ``PersonCodec`` is used to encode the document. When retrieving data, the same ``PersonCodec``
105
+ is used to decode BSON data into a ``Person`` instance. Note that while the ``PersonCodec`` could technically decode any
110
106
BSON document that contains a name field, we wouldn't want to use it for any other documents. Document codecs are meant
111
107
to be used in a collection, or when decoding embedded documents.
112
108
113
109
When working on a collection with a codec, the codec will only accept and return data of that type for certain
114
- operations. The ``bulkWrite``, ```findOneAndReplace``, ``insertMany``, ``insertOne``, and ``replaceOne`` operations
115
- will attempt to encode the given data using the provided codec. Trying to insert or replace a document that cannot be
116
- encoded will result in an exception. The ``aggregate``, ``find``, ``findOne``, ``findOneAndDelete``,
117
- ``findOneAndReplace``, and ``findOneAndUpdate`` operations will attempt to decode returned documents using the provided
118
- codec. If the codec does not support the data returned, an exception will be thrown. You can disable codec usage for a
119
- specific operation or use a different codec (e.g. to decode the result of an aggregation pipeline) by specifying the
120
- nullable ``codec`` option for the operation. This will override the collection-level codec:
110
+ operations. Insert and replace operations (e.g. ``insertOne``, ```findOneAndReplace``, and some ``bulkWrite``
111
+ operations) will attempt to encode the given data using the provided codec. Trying to insert or replace a document that
112
+ cannot be encoded will result in an exception. Read operations (e.g. ``aggregate``, ``find``, and ``findOneAndUpdate``)
113
+ operations will attempt to decode returned documents using the provided codec. If the codec does not support the data
114
+ returned, an exception will be thrown.
115
+
116
+ You can disable codec usage for a specific operation or use a different codec (e.g. to decode the result of an
117
+ aggregation pipeline) by specifying the ``null`` for the ``codec`` option for any operation. This will override the
118
+ collection-level codec:
121
119
122
120
.. code-block:: php
123
121
@@ -136,12 +134,14 @@ nullable ``codec`` option for the operation. This will override the collection-l
136
134
'codec' => null,
137
135
]);
138
136
139
- Generic Codecs
140
- --------------
137
+ Handling Fields and Data Types
138
+ ------------------------------
139
+
140
+ The previous example showed how to define a codec for a specific class. However, you may want to create a codec that
141
+ handles a particular data type in any document. This can be achieved by implementing the ``MongoDB\Codec\Codec``
142
+ interface.
141
143
142
- The previous example showed how to define a codec for a specific class. However, sometimes you want to define codecs to
143
- handle a given type in all documents. For such codecs, you can implement the ``MongoDB\Codec\Codec`` interface. The
144
- following example defines a codec to store ``DateTimeInterface`` instances as BSON dates including the timezone:
144
+ The following example defines a codec to store ``DateTimeInterface`` instances as BSON dates including the timezone:
145
145
146
146
.. code-block:: php
147
147
@@ -203,7 +203,7 @@ following example defines a codec to store ``DateTimeInterface`` instances as BS
203
203
}
204
204
}
205
205
206
- This codec can now be leveraged by other codecs encode and decode dates . Let's return to the previous example and add a
206
+ This codec can now be leveraged by other codecs handle date fields . Let's return to the previous example and add a
207
207
``createdAt`` field that contains the creation date. The modified encode and decode methods would look like this (other
208
208
code omitted for brevity):
209
209
@@ -213,11 +213,15 @@ code omitted for brevity):
213
213
214
214
final class PersonCodec implements MongoDB\Codec\DocumentCodec
215
215
{
216
+ use MongoDB\Codec\DecodeIfSupported;
217
+ use MongoDB\Codec\EncodeIfSupported;
218
+
216
219
public function __construct(
217
220
private readonly DateTimeCodec $dateTimeCodec = new DateTimeCodec(),
218
221
) {}
219
222
220
- // Other code omitted for brevity
223
+ // Other methods omitted for brevity
224
+
221
225
public function decode($value): Person
222
226
{
223
227
if (! $this->canDecode($value)) {
@@ -245,12 +249,12 @@ code omitted for brevity):
245
249
}
246
250
}
247
251
248
- Handling embedded documents
252
+ Handling Embedded Documents
249
253
---------------------------
250
254
251
- The previous example showed how to handle a single document. However, sometimes you want to handle fields that contain
252
- embedded documents. To show this, let's create an address document that we'll be embedding into our ``Person`` document.
253
- To ensure consistency, we're going to make this a readonly class:
255
+ A previous example showed how to handle a single document. However, sometimes you want to handle fields that contain
256
+ embedded documents. We will demonstrate this using an ``Address`` document, which we will embed within a ``Person``
257
+ document. To ensure consistency, we're going to make this a read-only class:
254
258
255
259
.. code-block:: php
256
260
@@ -274,7 +278,11 @@ We can now create a document codec for this class:
274
278
275
279
final class AddressCodec implements MongoDB\Codec\DocumentCodec
276
280
{
277
- // Other code omitted for brevity
281
+ use MongoDB\Codec\DecodeIfSupported;
282
+ use MongoDB\Codec\EncodeIfSupported;
283
+
284
+ // Other methods omitted for brevity
285
+
278
286
public function decode($value): Person
279
287
{
280
288
if (! $this->canDecode($value)) {
@@ -304,10 +312,7 @@ We can now create a document codec for this class:
304
312
}
305
313
}
306
314
307
- This codec is quite similar to the ``PersonCodec`` we had before, except that we're not adding an identifier to it. The
308
- creation of the object also differs, as we have to pass all the fields to the constructor.
309
-
310
- In the ``PersonCodec``, we can now extend the ``decode`` and ``encode`` methods to handle the address field. Note that
315
+ In the ``PersonCodec``, we can now modify the ``decode`` and ``encode`` methods to handle the address field. Note that
311
316
the example below excludes some code we've already shown in previous examples.
312
317
313
318
.. code-block:: php
@@ -359,10 +364,10 @@ the example below excludes some code we've already shown in previous examples.
359
364
Codec Libraries
360
365
---------------
361
366
362
- If you have a number of codecs that you want to use in multiple places, you can create a codec library. A codec library
363
- contains a list of codecs and checks each codec if it supports a value. If it does, it will use that codec to encode or
364
- decode the given value. The following code snippet changes the ``PersonCodec`` to use a codec library instead of a
365
- hard-coded ``DateTimeCodec``:
367
+ A codec library contains a list of codecs and presents itself as a codec. When encoding or decoding a value, it will
368
+ consult each registered codec in sequence and delegate to the first supporting codec to transform that value.
369
+
370
+ The following code snippet changes the ``PersonCodec`` to use a codec library instead of a hard-coded ``DateTimeCodec``:
366
371
367
372
.. code-block:: php
368
373
0 commit comments