Skip to content

Commit 7366f73

Browse files
committed
Address code review
1 parent 5c75a08 commit 7366f73

File tree

1 file changed

+52
-47
lines changed

1 file changed

+52
-47
lines changed

docs/tutorial/codecs.txt

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,27 @@ Overview
1616
--------
1717

1818
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).
2222

23-
Document Codec Usage
24-
--------------------
23+
Handling Documents
24+
------------------
2525

2626
The main logic is contained in a document codec. This class implements the ``MongoDB\Codec\DocumentCodec`` interface and
2727
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:
2929

3030
.. code-block:: php
3131

3232
<?php
3333

3434
final class Person
3535
{
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+
) {}
4440
}
4541

4642
.. code-block:: php
@@ -69,10 +65,10 @@ encode/decode it:
6965
throw UnsupportedValueException::invalidDecodableValue($value);
7066
}
7167

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+
);
7672
}
7773

7874
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
105101
$person = $collection->findOne();
106102

107103
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
110106
BSON document that contains a name field, we wouldn't want to use it for any other documents. Document codecs are meant
111107
to be used in a collection, or when decoding embedded documents.
112108

113109
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:
121119

122120
.. code-block:: php
123121

@@ -136,12 +134,14 @@ nullable ``codec`` option for the operation. This will override the collection-l
136134
'codec' => null,
137135
]);
138136

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.
141143

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:
145145

146146
.. code-block:: php
147147

@@ -203,7 +203,7 @@ following example defines a codec to store ``DateTimeInterface`` instances as BS
203203
}
204204
}
205205

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
207207
``createdAt`` field that contains the creation date. The modified encode and decode methods would look like this (other
208208
code omitted for brevity):
209209

@@ -213,11 +213,15 @@ code omitted for brevity):
213213

214214
final class PersonCodec implements MongoDB\Codec\DocumentCodec
215215
{
216+
use MongoDB\Codec\DecodeIfSupported;
217+
use MongoDB\Codec\EncodeIfSupported;
218+
216219
public function __construct(
217220
private readonly DateTimeCodec $dateTimeCodec = new DateTimeCodec(),
218221
) {}
219222

220-
// Other code omitted for brevity
223+
// Other methods omitted for brevity
224+
221225
public function decode($value): Person
222226
{
223227
if (! $this->canDecode($value)) {
@@ -245,12 +249,12 @@ code omitted for brevity):
245249
}
246250
}
247251

248-
Handling embedded documents
252+
Handling Embedded Documents
249253
---------------------------
250254

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:
254258

255259
.. code-block:: php
256260

@@ -274,7 +278,11 @@ We can now create a document codec for this class:
274278

275279
final class AddressCodec implements MongoDB\Codec\DocumentCodec
276280
{
277-
// Other code omitted for brevity
281+
use MongoDB\Codec\DecodeIfSupported;
282+
use MongoDB\Codec\EncodeIfSupported;
283+
284+
// Other methods omitted for brevity
285+
278286
public function decode($value): Person
279287
{
280288
if (! $this->canDecode($value)) {
@@ -304,10 +312,7 @@ We can now create a document codec for this class:
304312
}
305313
}
306314

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
311316
the example below excludes some code we've already shown in previous examples.
312317

313318
.. code-block:: php
@@ -359,10 +364,10 @@ the example below excludes some code we've already shown in previous examples.
359364
Codec Libraries
360365
---------------
361366

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``:
366371

367372
.. code-block:: php
368373

0 commit comments

Comments
 (0)