Skip to content

Commit 9880fe6

Browse files
committed
feat: implement attribute inheritance
1 parent d9d2b32 commit 9880fe6

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

docs/entity.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ class User
8080
- **Property Mapping**: the **name** argument is used to map the property to a DynamoDB attribute. This argument is
8181
optional and, if not provided, DynamoPHP will use the property's name as DynamoDB attribute's name.
8282

83+
## Inheritance
84+
85+
**DynamoPHP** supports _PHP attribute inheritance_. So if you are leveraging class inheritance in your application,
86+
**DynamoPHP attributes** will also be passed down and inherited from parent to child classes.
87+
8388
## Best practices
8489

8590
- **Define entities as simple value objects:** keep entities as lightweight as possible by using simple data types and

src/Metadata/MetadataLoader.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ private function getClassAttributes(ReflectionClass $reflection): array
102102
{
103103
$attributes = [];
104104

105+
$parentReflection = $reflection->getParentClass();
106+
107+
if ($parentReflection instanceof ReflectionClass) {
108+
$attributes = $this->getClassAttributes($parentReflection);
109+
}
110+
105111
foreach ($reflection->getAttributes() as $attribute) {
106112
$instance = $attribute->newInstance();
107113
$attributes[$instance::class] = $instance;
@@ -119,6 +125,12 @@ private function getPropertyAttributes(ReflectionClass $reflection): array
119125
{
120126
$attributes = [];
121127

128+
$parentReflection = $reflection->getParentClass();
129+
130+
if ($parentReflection instanceof ReflectionClass) {
131+
$attributes = $this->getPropertyAttributes($parentReflection);
132+
}
133+
122134
foreach ($reflection->getProperties() as $property) {
123135
$propertyAttributes = $property->getAttributes();
124136

tests/Unit/Metadata/MetadataLoaderTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use EduardoMarques\DynamoPHP\Metadata\MetadataLoader;
1010
use EduardoMarques\DynamoPHP\Tests\Unit\Stubs\ClassA;
1111
use EduardoMarques\DynamoPHP\Tests\Unit\Stubs\EntityA;
12+
use EduardoMarques\DynamoPHP\Tests\Unit\Stubs\EntityB;
1213
use PHPUnit\Framework\Attributes\Test;
1314
use PHPUnit\Framework\TestCase;
1415
use ReflectionProperty;
@@ -47,6 +48,32 @@ public function itReturnsEntityMetadata(): void
4748
$this->assertInstanceOf(Attribute::class, $attributes[1]);
4849
$this->assertInstanceOf(Attribute::class, $attributes[2]);
4950
$this->assertInstanceOf(Attribute::class, $attributes[3]);
51+
52+
$this->assertNull($propertyAttributes['name']->name);
53+
$this->assertSame('createdAt', $propertyAttributes['creationDate']->name);
54+
}
55+
56+
#[Test]
57+
public function itReturnsEntityMetadataMergedWithParent(): void
58+
{
59+
$metadata = $this->metadataLoader->getEntityMetadata(EntityB::class);
60+
61+
$this->assertSame('tests', $metadata->getTable());
62+
$this->assertSame(['id'], $metadata->getPartitionKey()->getFields());
63+
$this->assertSame(['creationDate'], $metadata->getSortKey()?->getFields());
64+
65+
$propertyAttributes = $metadata->getPropertyAttributes();
66+
$properties = array_keys($propertyAttributes);
67+
$attributes = array_values($propertyAttributes);
68+
69+
$this->assertSame(['id', 'name', 'creationDate', 'cardNumber', 'type'], $properties);
70+
$this->assertInstanceOf(Attribute::class, $attributes[0]);
71+
$this->assertInstanceOf(Attribute::class, $attributes[1]);
72+
$this->assertInstanceOf(Attribute::class, $attributes[2]);
73+
$this->assertInstanceOf(Attribute::class, $attributes[3]);
74+
75+
$this->assertSame('fullName', $propertyAttributes['name']->name);
76+
$this->assertNull($propertyAttributes['creationDate']->name);
5077
}
5178

5279
#[Test]

tests/Unit/Stubs/EntityA.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
partitionKey: new PartitionKey(['id']),
1717
sortKey: new SortKey(['creationDate'])
1818
)]
19-
final class EntityA
19+
class EntityA
2020
{
2121
#[Attribute]
2222
public int $id;

tests/Unit/Stubs/EntityB.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EduardoMarques\DynamoPHP\Tests\Unit\Stubs;
6+
7+
use DateTimeInterface;
8+
use EduardoMarques\DynamoPHP\Attribute\Attribute;
9+
10+
class EntityB extends EntityA
11+
{
12+
#[Attribute('fullName')]
13+
public string $name;
14+
15+
#[Attribute]
16+
public DateTimeInterface $creationDate;
17+
18+
#[Attribute]
19+
public string $type;
20+
}

0 commit comments

Comments
 (0)