From 5ed8f1aa3bf1857faba2c1845d86834909d1c89e Mon Sep 17 00:00:00 2001 From: Andrey Postal Date: Wed, 23 Jul 2025 19:38:58 -0300 Subject: [PATCH 1/2] Allow defining default value for hydration --- src/Attributes/Item.php | 1 + src/SimpleHydrator.php | 4 ++-- tests/HydratorTest.php | 19 +++++++++++++++++++ tests/Utils/TestObject.php | 4 ++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Attributes/Item.php b/src/Attributes/Item.php index 497b6f2..a0880ba 100644 --- a/src/Attributes/Item.php +++ b/src/Attributes/Item.php @@ -10,5 +10,6 @@ public function __construct( public ?string $key = null, public bool $required = false, public ?string $type = null, + public mixed $default = null, ) { } } diff --git a/src/SimpleHydrator.php b/src/SimpleHydrator.php index b968360..3911784 100644 --- a/src/SimpleHydrator.php +++ b/src/SimpleHydrator.php @@ -89,7 +89,7 @@ private function processProperty(ReflectionProperty $property, array $data, bool } if (!$arrKeyExists) { - return $this->buildNullableResponse($property, null); + return $this->buildNullableResponse($property, $item->default); } if ($property->getType()?->isBuiltin()) { @@ -134,7 +134,7 @@ private function handleBuiltin(array $data, string $key, ReflectionProperty $pro return new Payload(data: $output); } - // If no data is set, returns null which will be ignored by the set value, falling back to undefined or default value + // If no data is set, return null, which will be ignored by the set value, falling back to undefined or default value return $this->buildNullableResponse($property, $data[$key] ?? null); } diff --git a/tests/HydratorTest.php b/tests/HydratorTest.php index 32d3b62..2fcf5f3 100644 --- a/tests/HydratorTest.php +++ b/tests/HydratorTest.php @@ -158,4 +158,23 @@ public function testArrayWithWrongValuesWithChild(): void $this->expectExceptionMessage('expected array with items of type but found '); $hydrator->hydrate($data, TestObject::class); } + + /** + * @throws ReflectionException + */ + public function testDefaultValueFromItem(): void + { + $data = [ + 'missing_required' => 'Im here', + ]; + + $hydrator = new SimpleHydrator(); + /** @var TestObject $object */ + $object = $hydrator->hydrate($data, TestObject::class); + + $this->assertEquals('default name', $object->itemName); + $this->assertEquals(ChildObject::class, $object->singleChild::class); + $this->assertCount(0, $object->singleChild->andImAnArrayOfInt); + $this->assertEquals('default child name', $object->singleChild->iHaveAName); + } } diff --git a/tests/Utils/TestObject.php b/tests/Utils/TestObject.php index f860a6e..13365eb 100644 --- a/tests/Utils/TestObject.php +++ b/tests/Utils/TestObject.php @@ -44,13 +44,13 @@ public function __construct( #[Item(type: ImEnum::class)] public array $enumArr; - #[Item] + #[Item(default: 'default name')] public string $itemName; #[Item(required: true)] public string $missingRequired; - #[Item] + #[Item(default: new ChildObject('default child name', 'different one', []))] public ChildObject $singleChild; #[Item] From 970b3a0bad4dc2d68463fd82467c2a98e21c93ec Mon Sep 17 00:00:00 2001 From: Andrey Postal Date: Wed, 23 Jul 2025 19:42:40 -0300 Subject: [PATCH 2/2] Update README.md --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e75ee5..5e4a335 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ use \Andrey\PancakeObject\Attributes\Item; class MyObject { #[Item] public int $id; - #[Item] + #[Item(default: 'default name')] public string $name; } ``` @@ -110,6 +110,19 @@ class MyObject { The type option can be used to validate that all the items in an array have some desired type as well, like "string", "integer"... +You can define a default value for an item using the "default" field when using the Item attribute: + +```php +use \Andrey\PancakeObject\Attributes\Item; + +class MyObject { + #[Item] + public int $id; + #[Item(default: 'default name')] + public string $name; +} +``` + ### Hydrator and Serializer In order to hydrate some value object following the attribute rules, you just need to use the SimpleHydrator class.