@@ -7,45 +7,58 @@ to replace the existing implementation of a mapping type.
7
7
8
8
In order to create a new mapping type you need to subclass
9
9
``Doctrine\ODM\MongoDB\Types\Type `` and implement/override
10
- the methods. Here is an example skeleton of such a custom type
11
- class:
10
+ the methods.
11
+
12
+ The following example defines a custom type that stores ``DateTimeInterface ``
13
+ instances as an embedded document containing a BSON date and accompanying
14
+ timezone string. Those same embedded documents are then be translated back into
15
+ a ``DateTimeImmutable `` when the data is read from the database.
12
16
13
17
.. code-block :: php
14
18
15
19
<?php
16
20
17
21
namespace My\Project\Types;
18
22
23
+ use DateTimeImmutable;
24
+ use DateTimeZone;
19
25
use Doctrine\ODM\MongoDB\Types\ClosureToPHP;
20
26
use Doctrine\ODM\MongoDB\Types\Type;
21
27
use MongoDB\BSON\UTCDateTime;
22
28
23
- /**
24
- * My custom datatype.
25
- */
26
- class MyType extends Type
29
+ class DateTimeWithTimezoneType extends Type
27
30
{
28
31
// This trait provides default closureToPHP used during data hydration
29
32
use ClosureToPHP;
30
33
31
- public function convertToPHPValue($value): \DateTime
34
+ public function convertToPHPValue($value): DateTimeImmutable
32
35
{
33
- // This is called to convert a Mongo value to a PHP representation
34
- return $value->toDateTime();
36
+ $timeZone = new DateTimeZone($value['tz']);
37
+ $dateTime = $value['utc']
38
+ ->toDateTime()
39
+ ->setTimeZone($timeZone);
40
+
41
+ return DateTimeImmutable::createFromMutable($dateTime);
35
42
}
36
43
37
- public function convertToDatabaseValue($value): UTCDateTime
44
+ public function convertToDatabaseValue($value): array
38
45
{
39
- // This is called to convert a PHP value to its Mongo equivalent
40
- return new UTCDateTime($value);
46
+ if (! isset($value['utc'], $value['tz'])) {
47
+ throw new RuntimeException('Database value cannot be converted to date with timezone. Expected array with "utc" and "tz" keys.');
48
+ }
49
+
50
+ return [
51
+ 'utc' => new UTCDateTime($value),
52
+ 'tz' => $value->getTimezone()->getName(),
53
+ ];
41
54
}
42
55
}
43
56
44
57
Restrictions to keep in mind:
45
58
46
59
-
47
- If the value of the field is *NULL * the method
48
- `` convertToDatabaseValue() `` is not called.
60
+ If the value of the field is *NULL * the method `` convertToDatabaseValue() ``
61
+ is not called. You don't need to check for * NULL * values .
49
62
-
50
63
The ``UnitOfWork `` never passes values to the database convert
51
64
method that did not change in the request.
@@ -59,41 +72,38 @@ know about it:
59
72
60
73
// in bootstrapping code
61
74
62
- // ...
63
-
64
75
use Doctrine\ODM\MongoDB\Types\Type;
65
76
66
- // ...
67
-
68
77
// Adds a type. This results in an exception if type with given name is already registered
69
- Type::addType('mytype ', \My\Project\Types\MyType ::class);
78
+ Type::addType('date_with_timezone ', \My\Project\Types\DateTimeWithTimezoneType ::class);
70
79
71
80
// Overrides a type. This results in an exception if type with given name is not registered
72
- Type::overrideType('mytype ', \My\Project\Types\MyType ::class);
81
+ Type::overrideType('date_immutable ', \My\Project\Types\DateTimeWithTimezoneType ::class);
73
82
74
83
// Registers a type without checking whether it was already registered
75
- Type::registerType('mytype ', \My\Project\Types\MyType ::class);
84
+ Type::registerType('date_immutable ', \My\Project\Types\DateTimeWithTimezoneType ::class);
76
85
77
- As can be seen above, when registering the custom types in the
78
- configuration you specify a unique name for the mapping type and
79
- map that to the corresponding |FQCN |. Now you can use your new
80
- type in your mapping like this:
86
+ As can be seen above, when registering the custom types in the configuration you
87
+ specify a unique name for the mapping type and map that to the corresponding
88
+ |FQCN |. Now you can use your new type in your mapping like this:
81
89
82
90
.. configuration-block ::
83
91
84
92
.. code-block :: php
85
93
86
94
<?php
87
95
88
- class MyPersistentClass
96
+ use DateTimeImmutable;
97
+
98
+ class Thing
89
99
{
90
- #[Field(type: 'mytype ')]
91
- private \DateTime $field ;
100
+ #[Field(type: 'date_with_timezone ')]
101
+ public DateTimeImmutable $date ;
92
102
}
93
103
94
104
.. code-block :: xml
95
105
96
- <field field-name =" field" type =" mytype " />
106
+ <field field-name =" field" type =" date_with_timezone " />
97
107
98
108
.. |FQCN | raw :: html
99
109
<abbr title="Fully-Qualified Class Name">FQCN</abbr>
0 commit comments