@@ -9,6 +9,9 @@ In order to create a new mapping type you need to subclass
99``Doctrine\ODM\MongoDB\Types\Type `` and implement/override
1010the methods.
1111
12+ Date Example: Mapping DateTimeImmutable with Timezone
13+ -----------------------------------------------------
14+
1215The following example defines a custom type that stores ``DateTimeInterface ``
1316instances as an embedded document containing a BSON date and accompanying
1417timezone string. Those same embedded documents are then be translated back into
@@ -32,6 +35,7 @@ a ``DateTimeImmutable`` when the data is read from the database.
3235 // This trait provides default closureToPHP used during data hydration
3336 use ClosureToPHP;
3437
38+ /** @param array{utc: UTCDateTime, tz: string} $value */
3539 public function convertToPHPValue($value): DateTimeImmutable
3640 {
3741 if (!isset($value['utc'], $value['tz'])) {
@@ -46,6 +50,7 @@ a ``DateTimeImmutable`` when the data is read from the database.
4650 return DateTimeImmutable::createFromMutable($dateTime);
4751 }
4852
53+ /** @return array{utc: UTCDateTime, tz: string} */
4954 public function convertToDatabaseValue($value): array
5055 {
5156 if (!$value instanceof DateTimeImmutable) {
@@ -115,5 +120,85 @@ specify a unique name for the mapping type and map that to the corresponding
115120
116121 <field field-name =" field" type =" date_with_timezone" />
117122
123+ Custom Type Example: Mapping a Money Value Object
124+ -------------------------------------------------
125+
126+ You can create a custom mapping type for your own value objects or classes. For
127+ example, to map a ``Money `` value object using the `moneyphp/money library `_, you can
128+ implement a type that converts between this class and a BSON embedded document format.
129+
130+ This approach works for any custom class by adapting the conversion logic to your needs.
131+
132+ Example Implementation (using ``Money\Money ``)::
133+
134+ .. code-block :: php
135+
136+ <?php
137+
138+ namespace App\MongoDB\Types;
139+
140+ use Doctrine\ODM\MongoDB\Types\ClosureToPHP;
141+ use Doctrine\ODM\MongoDB\Types\Type;
142+ use InvalidArgumentException;
143+ use Money\Money;
144+ use Money\Currency;
145+
146+ final class MoneyType extends Type
147+ {
148+ // This trait provides a default closureToPHP used during data hydration
149+ use ClosureToPHP;
150+
151+ public function convertToPHPValue(mixed $value): ?Money
152+ {
153+ if (null === $value) {
154+ return null;
155+ }
156+
157+ if (is_array($value) && isset($value['amount'], $value['currency'])) {
158+ return new Money($value['amount'], new Currency($value['currency']));
159+ }
160+
161+ throw new InvalidArgumentException(sprintf('Could not convert database value from "%s" to %s', get_debug_type($value), Money::class));
162+ }
163+
164+ public function convertToDatabaseValue(mixed $value): ?array
165+ {
166+ if (null === $value) {
167+ return null;
168+ }
169+
170+ if ($value instanceof Money) {
171+ return [
172+ 'amount' => $value->getAmount(),
173+ 'currency' => $value->getCurrency()->getCode(),
174+ ];
175+ }
176+
177+ throw new InvalidArgumentException(sprintf('Could not convert database value from "%s" to array', get_debug_type($value)));
178+ }
179+ }
180+
181+ Register the type in your bootstrap code::
182+
183+ .. code-block :: php
184+
185+ Type::addType(Money::class, App\MongoDB\Types\MoneyType::class);
186+
187+ By using the |FQCN | of the value object class as the type name, the type is
188+ automatically used when encountering a property of that class. This means you
189+ can omit the ``type `` option when defining the field mapping::
190+
191+ .. code-block :: php
192+
193+ #[Field]
194+ public ?\Money\Money $price;
195+
196+ .. note ::
197+
198+ This implementation of ``MoneyType `` is kept simple for illustration purposes
199+ and does not handle all edge cases, but it should give you a good starting
200+ point for implementing your own custom types.
201+
202+ .. _`moneyphp/money library` : https://github.com/moneyphp/money
118203.. |FQCN | raw :: html
119204 <abbr title="Fully-Qualified Class Name">FQCN</abbr>
0 commit comments