When creating a new DTO in app/DataTransferObjects/Grenke/<Name>Data.php, follow these structural requirements:
- Constructor: Use only
public readonly properties. - fromArray(array $data): Implement this static method to map PascalCase external keys to camelCase properties. Use defensive defaults (e.g.,
?? null, ?? '', ?? 0) because the Grenke API may omit fields depending on the status. - toArray(): Implement this method to convert the DTO back into the PascalCase wire format.
- Nesting: For complex objects, recursively call
fromArray() and toArray() on nested DTOs.
namespace App\DataTransferObjects\Grenke;
class RequestPayloadData
{
public function __construct(
public readonly string $financingId,
public readonly string $productType,
public readonly float $financingAmount,
public readonly LesseeData $lessee,
public readonly array $financingObjects, // FinancingObjectData[]
) {}
public static function fromArray(array $data): self
{
return new self(
financingId: (string) ($data['FinancingId'] ?? ''),
productType: (string) ($data['ProductType'] ?? ''),
financingAmount: (float) ($data['FinancingAmount'] ?? 0),
lessee: LesseeData::fromArray($data['Lessee'] ?? []),
financingObjects: array_map(
fn (array $i) => FinancingObjectData::fromArray($i),
$data['FinancingObjects'] ?? []
),
);
}
public function toArray(): array
{
return [
'FinancingId' => $this->financingId,
'ProductType' => $this->productType,
'FinancingAmount' => $this->financingAmount,
'Lessee' => $this->lessee->toArray(),
'FinancingObjects' => array_map(
fn (FinancingObjectData $i) => $i->toArray(),
$this->financingObjects
),
];
}
}