Skip to content

Property Mapping

Learn how to map source keys to different property names using MapFrom attribute.

Property mapping allows you to map source data keys to different property names in your DTO:

class UserDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('full_name')]
public readonly string $name,
#[MapFrom('email_address')]
public readonly string $email,
) {}
}
$dto = UserDTO::fromArray([
'full_name' => 'John Doe',
'email_address' => 'john@example.com',
]);
echo $dto->name; // 'John Doe'
echo $dto->email; // 'john@example.com'
use Event4u\DataHelpers\SimpleDTO\Attributes\MapFrom;
class ProductDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('product_name')]
public readonly string $name,
#[MapFrom('product_price')]
public readonly float $price,
#[MapFrom('product_sku')]
public readonly string $sku,
) {}
}
class UserDTO extends SimpleDTO
{
public function __construct(
public readonly string $name,
#[MapFrom('contact.email')]
public readonly string $email,
#[MapFrom('contact.phone')]
public readonly ?string $phone = null,
) {}
}
$dto = UserDTO::fromArray([
'name' => 'John Doe',
'contact' => [
'email' => 'john@example.com',
'phone' => '+1234567890',
],
]);
class UserDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('user_id')]
public readonly int $id,
#[MapFrom('user_name')]
public readonly string $name,
#[MapFrom('user_email')]
public readonly string $email,
#[MapFrom('created_at')]
public readonly Carbon $createdAt,
) {}
}
// Map from API response
$dto = UserDTO::fromArray([
'user_id' => 1,
'user_name' => 'John Doe',
'user_email' => 'john@example.com',
'created_at' => '2024-01-15',
]);
class OrderDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('order_id')]
public readonly int $id,
#[MapFrom('customer_name')]
public readonly string $customerName,
#[MapFrom('order_total')]
public readonly float $total,
#[MapFrom('order_status')]
public readonly string $status,
) {}
}
class LegacyUserDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('usr_id')]
public readonly int $userId,
#[MapFrom('usr_nm')]
public readonly string $userName,
#[MapFrom('usr_eml')]
public readonly string $userEmail,
#[MapFrom('usr_crt_dt')]
public readonly Carbon $createdDate,
) {}
}
class EventDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('event_name')]
public readonly string $name,
#[MapFrom('event_date'), Cast(DateTimeCast::class)]
public readonly Carbon $date,
) {}
}
class UserDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('full_name'), Required, Min(3)]
public readonly string $name,
#[MapFrom('email_address'), Required, Email]
public readonly string $email,
) {}
}
// ✅ Good - clear property names
#[MapFrom('usr_nm')]
public readonly string $userName;
// ❌ Bad - unclear abbreviation
#[MapFrom('usr_nm')]
public readonly string $usrNm;
/**
* @property int $id Mapped from 'user_id'
* @property string $name Mapped from 'full_name'
*/
class UserDTO extends SimpleDTO
{
public function __construct(
#[MapFrom('user_id')]
public readonly int $id,
#[MapFrom('full_name')]
public readonly string $name,
) {}
}
// ✅ Good - map external API to clean internal names
#[MapFrom('external_api_field_name')]
public readonly string $cleanPropertyName;

The following working examples demonstrate this feature:

All examples are fully tested and can be run directly.

The functionality is thoroughly tested. Key test files:

Run the tests:

Terminal window
# Run tests
task test:unit -- --filter=PropertyMapping