Skip to content

Commit 99daa4e

Browse files
committed
Added documentation
1 parent 66fb1e5 commit 99daa4e

File tree

4 files changed

+129
-4
lines changed

4 files changed

+129
-4
lines changed

docs/DataRefiners.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
Data Refiners
2+
=
3+
4+
In the deserialization process, sometimes we may need to refine the data before it is passed to the deserializer.
5+
This is where Data Refiners come in.
6+
7+
A pretty good example would be DateTimes. When attempting to create an instanceof DateTime, we may need to
8+
be aware of specific formats that the DateTime can be created from.
9+
10+
By default, these are the DataRefiners that are available in the library:
11+
- [DateTimeRefiner](#DateTimeRefiner) - Refines the data to a DateTimeImmutable instance depending on the format provided.
12+
13+
DateTimeRefiner
14+
-
15+
16+
```php
17+
use Nuxtifyts\PhpDto\Data;
18+
use DateTimeImmutable;
19+
20+
final readonly class DateRangeData extends Data
21+
{
22+
public function __construct(
23+
public ?DateTimeImmutable $start,
24+
public ?DateTimeImmutable $end
25+
) {}
26+
}
27+
```
28+
29+
With this DTO, if we try to hydrate it with a custom format `'Y/m-d'`, it will fail.
30+
31+
```php
32+
DateRangeData::from([
33+
'start' => '2023/01-12',
34+
'end' => '2023/01-14'
35+
]);
36+
```
37+
38+
To resolve this, we may need to specify a Data Refiner that will help deserialize the data.
39+
40+
```php
41+
use Nuxtifyts\PhpDto\Data;
42+
use DateTimeImmutable;
43+
use Nuxtifyts\PhpDto\Attributes\Property\WithRefiner;
44+
use Nuxtifyts\PhpDto\DataRefiners\DateTimeRefiner;
45+
46+
final readonly class DateRangeData extends Data
47+
{
48+
public function __construct(
49+
#[WithRefiner(DateTimeRefiner::class, formats: 'Y/m-d')]
50+
public ?DateTimeImmutable $start,
51+
#[WithRefiner(DateTimeRefiner::class, formats: 'Y/m-d')]
52+
public ?DateTimeImmutable $end
53+
) {}
54+
}
55+
```
56+
57+
With this, hydrating the DTO will be possible.
58+
59+
Creating a Custom Data Refiner
60+
=
61+
62+
To create a custom Data Refiner, you need to implement the `DataRefiner` interface. for example suppose we
63+
want to create a Data Refiner that will refine an object of class `CustomDate`:
64+
65+
```php
66+
class CustomDate {
67+
public function __construct(
68+
private(set) int $year,
69+
private(set) int $month,
70+
private(set) int $day
71+
) {}
72+
73+
// ...
74+
}
75+
```
76+
77+
We can add the ability to hydrate a `DateTime` property from this class using a custom refiner like so:
78+
79+
```php
80+
use Nuxtifyts\PhpDto\Contexts\PropertyContext;
81+
use Nuxtifyts\PhpDto\DataRefiners\DataRefiner;
82+
83+
84+
class CustomDateRefiner implements DataRefiner
85+
{
86+
public function refine(mixed $value, PropertyContext $property) : mixed
87+
{
88+
if ($value instanceof CustomDate) {
89+
return DateTimeImmutable::createFromFormat(
90+
format: 'Y-m-d',
91+
datetime: sprintf('%d-%d-%d', $value->year, $value->month, $value->day)
92+
);
93+
}
94+
95+
return $value;
96+
}
97+
}
98+
```
99+
100+
Now we can use this refiner in our previous DTO:
101+
102+
```php
103+
use Nuxtifyts\PhpDto\Data;
104+
use DateTimeImmutable;
105+
use Nuxtifyts\PhpDto\Attributes\Property\WithRefiner;
106+
use Nuxtifyts\PhpDto\DataRefiners\DateTimeRefiner;
107+
108+
final readonly class DateRangeData extends Data
109+
{
110+
public function __construct(
111+
#[WithRefiner(DateTimeRefiner::class, formats: 'Y/m-d')]
112+
#[WithRefiner(CustomDateRefiner::class)]
113+
public ?DateTimeImmutable $start,
114+
#[WithRefiner(CustomDateRefiner::class)]
115+
#[WithRefiner(DateTimeRefiner::class, formats: 'Y/m-d')]
116+
public ?DateTimeImmutable $end
117+
) {}
118+
}
119+
```

docs/Quickstart.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,4 @@ can be found here:
7979
- [Supported Types](https://github.com/nuxtifyts/php-dto/blob/main/docs/SupportedTypes.md)
8080
- [Normalizers](https://github.com/nuxtifyts/php-dto/blob/main/docs/Normalizers.md)
8181
- [Property Attributes](https://github.com/nuxtifyts/php-dto/blob/main/docs/PropertyAttributes.md)
82+
- [Data Refiners](https://github.com/nuxtifyts/php-dto/blob/main/docs/DataRefiners.md)

src/DataRefiners/DateTimeRefiner.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ public function __construct(
2424
string|array|null $formats = null
2525
) {
2626
if (!is_null($formats)) {
27-
$this->formats = is_string($formats) ? [$formats] : $formats;
27+
if (is_string($formats)) {
28+
$this->formats[] = $formats;
29+
} else {
30+
$this->formats = array_values(array_unique([
31+
...$this->formats,
32+
...$formats
33+
]));
34+
}
2835
}
2936
}
3037

tests/Unit/DataRefiners/DateTimeRefinerTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Nuxtifyts\PhpDto\Tests\Unit\DataRefiners;
44

55
use Nuxtifyts\PhpDto\Attributes\Property\WithRefiner;
6-
use Nuxtifyts\PhpDto\Contexts\ClassContext;
76
use Nuxtifyts\PhpDto\Contexts\PropertyContext;
87
use Nuxtifyts\PhpDto\Data;
98
use Nuxtifyts\PhpDto\DataRefiners\DateTimeRefiner;
@@ -15,7 +14,6 @@
1514
use PHPUnit\Framework\Attributes\DataProvider;
1615
use PHPUnit\Framework\Attributes\Test;
1716
use PHPUnit\Framework\Attributes\UsesClass;
18-
use ReflectionClass;
1917
use ReflectionProperty;
2018
use DateTimeInterface;
2119
use DateTimeImmutable;
@@ -75,7 +73,7 @@ public function __construct(
7573
);
7674

7775
self::expectException(InvalidRefiner::class);
78-
$refinedValue = new DateTimeRefiner()->refine('2025-06-17', $propertyContext);
76+
new DateTimeRefiner()->refine('2025-06-17', $propertyContext);
7977
}
8078

8179
/**

0 commit comments

Comments
 (0)