Skip to content

Commit 9331ab6

Browse files
committed
Fix array castings for nested objects
1 parent 8c75fc7 commit 9331ab6

File tree

5 files changed

+112
-22
lines changed

5 files changed

+112
-22
lines changed

src/DtoSerialize.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,18 @@ public static function serializeSingle( Dto $dto ): \stdClass
3838
/**
3939
* @param Dto $dto
4040
* @param array $arr
41+
* @param bool $toSnakeCase
42+
* @param bool $includeNulls
43+
* @param string $keyPrefix
4144
* @return array
4245
*/
43-
public static function castToArray( Dto $dto, array $arr = [] ): array
46+
public static function castToArray(
47+
Dto $dto,
48+
array $arr = [],
49+
bool $toSnakeCase = false,
50+
bool $includeNulls = false,
51+
string $keyPrefix = ''
52+
): array
4453
{
4554
$vars = $dto->getObjectVars();
4655

@@ -49,9 +58,21 @@ public static function castToArray( Dto $dto, array $arr = [] ): array
4958
$key = str_replace('_', '', $key);
5059
$temp = [];
5160

61+
$key = $toSnakeCase ?
62+
ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $key)), '_') :
63+
lcfirst($key);
64+
65+
$key = "{$keyPrefix}{$key}";
66+
5267
if($value instanceof Dto)
5368
{
54-
$temp = self::castToArray($value, $temp);
69+
$temp = self::castToArray(
70+
dto: $value,
71+
arr: $temp,
72+
toSnakeCase: $toSnakeCase,
73+
includeNulls: $includeNulls,
74+
keyPrefix: $keyPrefix,
75+
);
5576
$arr[$key] = $temp;
5677
}
5778
else

src/ToArray.php

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,11 @@ public function toArray(
1818
string $keyPrefix = ''
1919
): array
2020
{
21-
$arr = self::castToArray($this);
22-
23-
$result = [];
24-
25-
foreach ($arr as $key => $value)
26-
{
27-
$key = $toSnakeCase ?
28-
ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $key)), '_') :
29-
lcfirst($key);
30-
31-
$key = "{$keyPrefix}{$key}";
32-
33-
if($value !== null || $includeNulls)
34-
{
35-
$result[$key] = $value;
36-
}
37-
}
38-
39-
return $result;
21+
return self::castToArray(
22+
dto: $this,
23+
toSnakeCase: $toSnakeCase,
24+
includeNulls: $includeNulls,
25+
keyPrefix: $keyPrefix
26+
);
4027
}
4128
}

tests/Unit/DtoTest.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Tests\Unit\Mock\MockDto;
66
use PHPUnit\Framework\TestCase;
7+
use Tests\Unit\Mock\MockSubDto;
78

89
class DtoTest extends TestCase
910
{
@@ -16,7 +17,15 @@ protected function setUp(): void
1617
$this->_mockData = [
1718
'name' => 'Mock name',
1819
'count' => 4,
19-
'is_true' => true
20+
'is_true' => true,
21+
'sub_dto' => new MockSubDto([
22+
'sub_name' => 'Mock sub name',
23+
'sub_count' => 5,
24+
'sub_sub_dto' => [
25+
'sub_name' => 'Mock sub sub name',
26+
'sub_count' => 6,
27+
]
28+
]),
2029
];
2130
}
2231

@@ -95,5 +104,13 @@ public function testToArray()
95104
$this->assertEquals( $this->_mockData['name'], $arr["{$keyPrefix}name"] );
96105
$this->assertEquals( $this->_mockData['count'], $arr["{$keyPrefix}count"] );
97106
$this->assertEquals( $this->_mockData['is_true'], $arr["{$keyPrefix}is_true"] );
107+
108+
$arr = $dto->toArray();
109+
110+
$this->assertEquals( $this->_mockData['sub_dto']->getSubName(), $arr['sub_dto']['sub_name'] );
111+
$this->assertEquals( $this->_mockData['sub_dto']->getSubCount(), $arr['sub_dto']['sub_count'] );
112+
113+
$this->assertEquals( $this->_mockData['sub_dto']->getSubSubDto()->getSubName(), $arr['sub_dto']['sub_sub_dto']['sub_name'] );
114+
$this->assertEquals( $this->_mockData['sub_dto']->getSubSubDto()->getSubCount(), $arr['sub_dto']['sub_sub_dto']['sub_count'] );
98115
}
99116
}

tests/Unit/Mock/MockDto.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@ class MockDto extends Dto
1010
use ToArray;
1111

1212
private ?string $_name;
13+
1314
private int $_count;
15+
1416
private bool $_isTrue;
1517

18+
private ?MockSubDto $_subDTO;
19+
1620
public function __construct( array $data )
1721
{
1822
$this->_name = $data['name'];
1923
$this->_count = $data['count'];
2024
$this->_isTrue = $data['is_true'];
25+
$this->_subDTO = $data['sub_dto'] ?? null;
2126
}
2227

2328
/**
@@ -43,4 +48,12 @@ public function getIsTrue(): bool
4348
{
4449
return $this->_isTrue;
4550
}
51+
52+
/**
53+
* @return MockSubDto|null
54+
*/
55+
public function getSubDTO(): ?MockSubDto
56+
{
57+
return $this->_subDTO;
58+
}
4659
}

tests/Unit/Mock/MockSubDto.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Tests\Unit\Mock;
4+
5+
use PhpDto\Dto;
6+
use PhpDto\ToArray;
7+
8+
class MockSubDto extends Dto
9+
{
10+
use ToArray;
11+
12+
private ?string $_subName;
13+
14+
private int $_subCount;
15+
16+
private ?self $_subSubDto;
17+
18+
public function __construct( array $data )
19+
{
20+
$this->_subName = $data['sub_name'];
21+
$this->_subCount = $data['sub_count'];
22+
23+
if(isset($data['sub_sub_dto']))
24+
{
25+
$this->_subSubDto = new self($data['sub_sub_dto']);
26+
}
27+
}
28+
29+
/**
30+
* @return string|null
31+
*/
32+
public function getSubName(): ?string
33+
{
34+
return $this->_subName;
35+
}
36+
37+
/**
38+
* @return int
39+
*/
40+
public function getSubCount(): int
41+
{
42+
return $this->_subCount;
43+
}
44+
45+
/**
46+
* @return self|null
47+
*/
48+
public function getSubSubDto(): ?self
49+
{
50+
return $this->_subSubDto;
51+
}
52+
}

0 commit comments

Comments
 (0)