dldash/data-transfer-object

Data transfer objects.

1.0.0 2020-12-31 11:51 UTC

This package is auto-updated.

Last update: 2024-04-29 04:46:35 UTC


README

Latest Version License Total Downloads Build

⚡️ Requirements

  • 🐘 PHP >= 8.0

💥 Installation

composer require dldash/data-transfer-object

✨ Usage

Simple DTO

If extra fields are passed that are not described in the DTO class, they will be ignored.

DTO class:

use Dldash\DataTransferObject\Models\DataTransferObject;

class UserDto extends DataTransferObject
{
    public function __construct(
        public int $userId,
        public string|null $username
    ) {}
}

Usage:

$request = [
    'userId' => 100,
    'username' => 'admin',
    'emailAddress' => 'admin@test.com'
];

$dto = UserDto::create($request);

Value Objects

You can also use value objects in DTO classes.
All you need is to implement the ValueObjectContract interface.

Value object class:

use Dldash\DataTransferObject\Contracts\ValueObjectContract;

class EmailAddress implements ValueObjectContract, JsonSerializable
{
    public function __construct(private string $value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException("Email address [${value}] is not valid.");
        }

        $this->value = strtolower($value);
    }

    public function value(): string
    {
        return $this->value;
    }

    public function jsonSerialize(): string
    {
        return $this->value;
    }
}

DTO class:

use Dldash\DataTransferObject\Models\DataTransferObject;

class OrderDto extends DataTransferObject
{
    public function __construct(
        public int $orderId,
        public EmailAddress $emailAddress
    ) {}
}

Usage:

$request = [
    'orderId' => 100,
    'emailAddress' => 'admin@test.com'
];

$dto = OrderDto::create($request);

Nested DTO classes

DTO class:

use Dldash\DataTransferObject\Models\DataTransferObject;

class OrderDto extends DataTransferObject
{
    public function __construct(
        public int $orderId,
        public UserDto $user
    ) {}
}

Usage:

$request = [
    'orderId' => 100,
    'user' => [
        'userId' => 100,
        'username' => 'admin'
    ]
];

$dto = OrderDto::create($request);

Typed DTO arrays and collections

You can use arrays of DTO objects.
To do this, you need to inherit the abstract DataTransferObjectCollection class.

Collection class:

use Dldash\DataTransferObject\Objects\DataTransferObjectCollection;

/** @method ArrayIterator|UserDto[] getIterator() */
class UserDtoCollection extends DataTransferObjectCollection
{
    protected function create(mixed $item): object
    {
        return UserDto::create($item);
    }
}

DTO class:

use Dldash\DataTransferObject\Models\DataTransferObject;

class OrderDto extends DataTransferObject
{
    public function __construct(
        public int $orderId,
        public UserDtoCollection $users
    ) {}
}

Usage:

$request = [
    'orderId' => 100,
    'users' => [
        [
            'userId' => 100,
            'username' => 'admin'
        ],
        [
            'userId' => 200,
            'username' => null
        ]
    ]
];

$dto = OrderDto::create($request);

Partial update

Let's imagine that we need to update some model, but we want to do a partial update. In this case, not all the required fields can be passed to the DTO class. You can add the Undefined type to the desired field.

NOTE: If you pass a null value, it will also be null.

DTO class:

use Dldash\DataTransferObject\Objects\Undefined;
use Dldash\DataTransferObject\Models\DataTransferObject;

class OrderDto extends DataTransferObject
{
    public function __construct(
        public int $orderId,
        public string|null|Undefined $name
    ) {}
}

Usage:

use Dldash\DataTransferObject\Objects\Undefined;

$request = [
    'orderId' => 100
];

$dto = OrderDto::create($request);

if (Undefined::isPresent($dto->name)) {
    // Update this field
}

Serialized name

DTO class:

use Dldash\DataTransferObject\Attributes\SerializedName;
use Dldash\DataTransferObject\Models\DataTransferObject;

class OrderDto extends DataTransferObject
{
    public function __construct(
        #[SerializedName('order_id')]
        public int $id,

        #[SerializedName('order_name')]
        public string $name
    ) {}
}

Usage:

$request = [
    'order_id' => 100,
    'order_name' => 'Order'
];

$dto = OrderDto::create($request);

echo $dto->id; // 100
echo $dto->name; // Order
echo json_encode($dto); // {"order_id": 100, "order_name": "Order"}

💫 Testing

composer test