matephp / dto
MatePHP - DTO - Simple Data Transfer Objects (DTO) for any framework
Requires
- php: ^8.2
Requires (Dev)
- pestphp/pest: ^3.7
- phpmd/phpmd: ^2.15
- phpstan/phpstan: ^2.1
- squizlabs/php_codesniffer: ^3.10
README
Mate - DTO
Simple Data Transfer Objects (DTO) for any framework
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.