matephp/dto

MatePHP - DTO - Simple Data Transfer Objects (DTO) for any framework

1.3.1 2025-06-06 19:04 UTC

This package is auto-updated.

Last update: 2025-07-06 19:24:29 UTC


README

Mate - DTO

Simple Data Transfer Objects (DTO) for any framework

Repo Latest Stable Version Unstable Version PHP from Packagist Total Downloads License Hits-of-Code

A DTO, or Data Transfer Object, is a design pattern used to transfer data between different layers or subsystems of an application. Its main function is to encapsulate data and minimize the number of calls to the database or other services.

Key features of DTOs:

  • Simplicity: DTOs are simple objects that only contain data and no business logic.
  • Encapsulation: DTOs encapsulate data, allowing you to control how information is accessed and modified.
  • Efficiency: DTOs can improve performance by reducing the amount of data transferred between layers.
  • Decoupling: DTOs help decouple different layers of an application, making code maintenance and evolution easier.

Some use cases:

  • When you need to transfer data between different layers of an application, such as the presentation layer and the data layer.
  • When you need to expose data through an API.
  • When you need to optimize the performance of your application by reducing the amount of data being transferred.

Instalation

Via Composer

composer require matephp/dto

Documentation

Define DTO properties

Properties can be set in the class definition or in the constructor (Constructor Property Promotion)

use Mate\Dto\Dto;

class MyDto extends Dto
{
    public string $property1;
    public string $property2;
}

// or

class MyDto extends Dto
{
    public function __constuct(
        public string $property1,
        public string $property2
    ) {
    }
}

DTO instantation

You can create DATA in different ways:

Using constructor

// ...

$dto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

From array using fromArray static method

// ...

$data = [
    "property1" => 'value 1',
    "property2" => 'value 2',
];

$dto = MyDto::fromArray($data);

From object using fromObject static method

// ...

$data = new stdClass();
$data->property1 = "value 1";
$data->property2 = "value 2";

$dto = MyDto::fromObject($data);

From json string using fromJson static method

// ...

$obj = new stdClass();
$obj->property1 = "value 1";
$obj->property2 = "value 2";

$data = json_encode($obj);

$dto = MyDto::fromJson($data);

from other DTO instance using fromDto static method

// ...

$otherDto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

$dto = MyDto::fromDto($otherDto);

Creating DTOs with dynamic properties (Flexible DTO)

To create a DTO that allows defining properties dynamically, the attribute #[Flexible] is used

use Mate\Dto\Dto;
use Mate\Dto\Attributes\Flexible;

#[Flexible]
class MyFlexibleDTo extends Dto
{
    public function __constructor(
        public string $property1,
        public string $property2
    ) {
    }
}

$dto = new MyFlexibleDTo(
    property1: 'value 1',
    property2: 'value 2',
    property3: 'value 3'
);

echo $dto->property3; // print: value 3

When creating a DTO with dynamic properties but not setting the #[Flexible] attribute, an exception of type Mate\Dto\Exceptions\NotFlexibleException is thrown.

Access DTO data

DTO data can be accessed as a property of an object or through array syntax

// ...

$dto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

echo $dto->property1; // print: value 1
echo $dto->property2; // print: value 2

echo $dto['property1']; // print: value 1
echo $dto['property2']; // print: value 2

Uninitialized properties

When an attribute is called that was not initialized, an \Error exception is thrown.

// ...

$dto = new MyDto(
    property1: 'value 1',
);

echo $dto->property2; // throw: \Error exception

Properties with default value

When a value is not sent to a property, the default value is used if it has one.

use Mate\Dto\Dto;

class MyDto extends Dto
{
    public function __constructor(
        public string $property1,
        public string $property2 = 'value 2'
    ) {
    }
}

$dtoA = new MyDto(
    property1: 'value 1',
);

$dtoB = new MyDto(
    property1: 'value 1',
    property2: 'other value'
);

echo $dtoA->property2; // print: value 2
echo $dtoA->property2; // print: other value

Nullable Properties

When a value is not sent to a nullable property it is automatically set to null.

use Mate\Dto\Dto;

class MyDto extends Dto
{
    public string $property1;
    public ?string $property2;
}

$dtoA = new MyDto(
    property1: 'value 1',
);

$dtoB = new MyDto(
    property1: 'value 1',
    property2: 'value 2';
);

echo $dtoA->property2; // print: null
echo $dtoB->property2; // print: value 2

Ignored attributes

You can ignore attributes so that they are not initialized and are not considered.

use Mate\Dto\Dto;
use Mate\Dto\Attributes\Ignored;

class MyDto extends Dto
{
    #[Ignored]
    public string $property1;
    public string $property2;
}

$dto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

echo $dto->property1; // throw: \Error exception

Transforming data

You can convert your DTO to some formats:

To array

// ...

$dto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

echo print_r($dto->toArray, true);
// print:
// Array
// (
//     [property1] => value 1
//     [property2] => value 2
// )

If you do not need to transform the attributes of the DTO type into an array, you can set it to false.

use Mate\Dto\Dto;

class MyDtoWithoutNestedToArray extends Dto
{
    protected bool $nestedToArrayEnabled = false;
    // ...
}

To database

// ...

class Client extends Dto
{
    public int $id;
    public int $userId;
}

$dto = new MyDto(
    id: 1,
    userId: 2,
);

echo print_r($dto->toDatabase, true);
// print:
// Array
// (
//     [id] => 1
//     [user_id] => 2
// )

To JSON string

// ...

$dto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

echo print_r($dto->toJson, true);
// print: {"property1":"value 1","property2":"value 2"}

To string

// ...

$dto = new MyDto(
    property1: 'value 1',
    property2: 'value 2',
);

echo print_r((string) $dto, true);
// print: {"property1":"value 1","property2":"value 2"}

Testing

composer test

// or with coverage

composer test-coverage

QA Tools

composer phpcs
composer phpstan
composer phpmd

License

MIT license. Please see the license file for more information.