@@ -228,6 +228,120 @@ code omitted for brevity):
228
228
}
229
229
}
230
230
231
+ Handling embedded documents
232
+ ---------------------------
233
+
234
+ The previous example showed how to handle a single document. However, sometimes you want to handle fields that contain
235
+ embedded documents. To show this, let's create an address document that we'll be embedding into our ``Person`` document.
236
+ To ensure consistency, we're going to make this a readonly class:
237
+
238
+ .. code-block:: php
239
+
240
+ <?php
241
+
242
+ final readonly class Address
243
+ {
244
+ public function __construct(
245
+ public string $street,
246
+ public string $postCode,
247
+ public string $city,
248
+ public string $country,
249
+ ) {
250
+ }
251
+
252
+ We can now create a document codec for this class:
253
+
254
+ .. code-block:: php
255
+
256
+ <?php
257
+
258
+ final class AddressCodec implements MongoDB\Codec\DocumentCodec
259
+ {
260
+ // Other code omitted for brevity
261
+ public function decode($value): Person
262
+ {
263
+ if (! $this->canDecode($value)) {
264
+ throw UnsupportedValueException::invalidDecodableValue($value);
265
+ }
266
+
267
+ return new Address(
268
+ $value->get('street'),
269
+ $value->get('postCode'),
270
+ $value->get('city'),
271
+ $value->get('country'),
272
+ );
273
+ }
274
+
275
+ public function encode($value): MongoDB\BSON\Document
276
+ {
277
+ if (! $this->canEncode($value)) {
278
+ throw UnsupportedValueException::invalidEncodableValue($value);
279
+ }
280
+
281
+ return MongoDB\BSON\Document::fromPHP([
282
+ 'street' => $value->street,
283
+ 'postCode' => $value->postCode,
284
+ 'city' => $value->city,
285
+ 'country' => $value->country,
286
+ ]);
287
+ }
288
+ }
289
+
290
+ This codec is quite similar to the ``PersonCodec`` we had before, except that we're not adding an identifier to it. The
291
+ creation of the object also differs, as we have to pass all the fields to the constructor.
292
+
293
+ In the ``PersonCodec``, we can now extend the ``decode`` and ``encode`` methods to handle the address field. Note that
294
+ the example below excludes some code we've already shown in previous examples.
295
+
296
+ .. code-block:: php
297
+
298
+ <?php
299
+
300
+ final class PersonCodec implements MongoDB\Codec\DocumentCodec
301
+ {
302
+ private AddressCodec $addressCodec;
303
+
304
+ public function __construct()
305
+ {
306
+ $this->addressCodec = new AddressCodec();
307
+ }
308
+
309
+ // Other code omitted for brevity
310
+ public function decode($value): Person
311
+ {
312
+ if (! $this->canDecode($value)) {
313
+ throw UnsupportedValueException::invalidDecodableValue($value);
314
+ }
315
+
316
+ $person = new Person($value->get('name'));
317
+ $person->id = $value->get('_id');
318
+
319
+ if ($value->has('address')) {
320
+ $person->address = $this->addressCodec->decode($value->get('address'));
321
+ }
322
+
323
+ return $person;
324
+ }
325
+
326
+ public function encode($value): MongoDB\BSON\Document
327
+ {
328
+ if (! $this->canEncode($value)) {
329
+ throw UnsupportedValueException::invalidEncodableValue($value);
330
+ }
331
+
332
+ $data = [
333
+ '_id' => $value->id,
334
+ 'name' => $value->name,
335
+ ];
336
+
337
+ if ($value->address) {
338
+ $data['address'] = $this->addressCodec->encode($value->address);
339
+ }
340
+
341
+ return MongoDB\BSON\Document::fromPHP($data);
342
+ }
343
+ }
344
+
231
345
Codec Libraries
232
346
---------------
233
347
0 commit comments