petrenkoanton / php-dto
Custom dto implementation
Requires
- php: ^8.1
- petrenkoanton/key-normalizer: ^2.0
- petrenkoanton/php-collection: ^1.0
Requires (Dev)
- php-coveralls/php-coveralls: ^2.7
- phpunit/phpunit: ^9.0
- psalm/plugin-phpunit: ^0.18.4
- ramsey/coding-standard: ^2.1
- squizlabs/php_codesniffer: ^3.8
- vimeo/psalm: ^5.16
README
Installation | Functionality | Usage | For developers | License | Related projects
Installation
Requirements
- php 8.1 or higher
Composer
composer require petrenkoanton/php-dto
Functionality
Public methods
Dto
All getters are provided using the __call()
magic method.
Method | Exception |
---|---|
__construct(array $data) | DtoException |
__call(string $name, array $arguments): mixed | DtoException |
toArray(): array | - |
DtoCollection
Method | Exception |
---|---|
__construct(Dto ...$items) | DtoException |
add(Collectable $item): void | DtoException |
Parent Collection
github.com/PetrenkoAnton/php-collection
Method | Exception |
---|---|
filter(callable $callback): Collection | - |
getItems(): array | - |
getItem(int $key): Collectable | CollectionException |
first(): Collectable | CollectionException |
count(): int | - |
Exceptions
Main library exception is DtoException.
There are 3 groups of exceptions: InitDtoException, SetupDtoException and HandleDtoException
Code | Message pattern | Exception | Group |
---|---|---|---|
101 | Dto: %s | Property: %s | Err: Missed property type declaration | NoTypeDeclarationException | InitDtoException |
102 | Dto: %s | Property: %s | Err: Unsupported mixed property type declaration | MixedDeclarationException | InitDtoException |
103 | Dto: %s | Property: %s | Err: Unsupported object property type declaration | ObjectDeclarationException | InitDtoException |
104 | Dto: %s | Property: %s | Err: Class must implement DtoInterface | NotDtoClassDeclarationException | InitDtoException |
105 | Dto: %s | Property: %s | Err: No backing value for enum | EnumNoBackingValueException | InitDtoException |
106 | DtoCollection: %s | Err: Invalid constructor declaration | DtoCollectionConstructorException | InitDtoException |
201 | DtoCollection: %s | Expected Dto: %s | Given Dto: %s | AddDtoException | SetupDtoException |
202 | Dto: %s | Property: %s | Err: No data | InputDataException | SetupDtoException |
203 | Dto: %s | Property: %s | Expected type: %s | Given type: %s | Value: %s | SetValueException | SetupDtoException |
204 | Dto: %s | Property: %s | Enum: %s | Expected values: %s | Given type: %s | Value: %s | SetValueEnumException | SetupDtoException |
301 | Dto: %s | %s | GetValueException | HandleDtoException |
Usage
Initialization
- Your dto class must extends
Dto\Dto
abstract class. - You need to declare available
protected
properties.
Important! Getter will be with the prefix is*
if property is a bool
type.
Simple DTO
<?php declare(strict_types=1); use Dto\Dto; /** * @method int getPrice() * @method string getType() * @method array getInfo() * @method bool isAvailable() */ class ProductDto extends Dto { protected int $price; protected string $type; protected array $info; protected bool $available; } // Array or instance of Arrayable interface $info = [ 'key' => 'value', ]; $data = [ 'price' => 999, 'type' => 'ticket', 'info' => $info, 'available' => true, ]; $dto = new ProductDto($data); $price = $dto->getPrice(); // 999 $type = $dto->getType(); // 'ticket' $info = $dto->getInfo(); // ['key' => 'value'] $available = $dto->isAvailable(); // true
Nested DTO (with Collection and Enum)
<?php declare(strict_types=1); use Collection\Arrayable; use Dto\Dto; use Dto\DtoCollection; /** * @method string getName() * @method int getAge() */ class PersonDto extends Dto { protected string $name; protected int $age; } class PersonDtoCollection extends DtoCollection { public function __construct(PersonDto ...$items) { parent::__construct(...$items); } } /** * @method int getPrice() * @method string getType() * @method array getInfo() * @method bool isAvailable() */ class ProductDto extends Dto { protected int $price; protected string $type; protected array $info; protected bool $available; } enum ColorEnum: string { case Red = 'red'; case Black = 'black'; case White = 'white'; } /** * @method PersonDtoCollection getPersons() * @method ProductDto getProduct() * @method ColorEnum getColor() */ class NestedDto extends Dto { protected PersonDtoCollection $persons; protected ProductDto $product; protected ColorEnum $color; } class NestedDtoFactory { public function create(array $data): NestedDto { return new NestedDto($data); } } class InfoArrayable implements Arrayable { public function toArray(): array { return [ 'key' => 'value', ]; } } $data = [ 'persons' => [ [ 'name' => 'Alice', 'age' => 25, ], [ 'name' => 'Bob', 'age' => 30, ], ], 'product' => [ 'price' => 999, 'type' => 'ticket', 'info' => new InfoArrayable(), 'available' => true, ], 'color' => 'red', ]; $nestedDto = (new NestedDtoFactory())->create($data); $personsCount = $nestedDto->getPersons()->count() // 2 $aliceDto = $nestedDto->getPersons()->first(); $aliceName = $aliceDto->getName(); // 'Alice' $aliceAge = $aliceDto->getAge(); // 25 $bobDto = $nestedDto->getPersons()->filter( fn (PersonDto $personDto) => $personDto->getName() === 'Bob' )->first(); $bobName = $bobDto->getName(); // 'Bob' $bobAge = $bobDto->getAge(); // '30' $productDto = $nestedDto->getProduct(); $productPrice = $productDto->getPrice(); // 999 $productInfo = $productDto->getInfo(); // ['key' => 'value'] $color = $nestedDto->getColor(); // ColorEnum::Red $colorValue = $colorEnum->value; // 'red'
Return DTO as array
<?php declare(strict_types=1); use Dto\Dto; use Dto\KeyCase; /** * @method int getActualNumber() * @method string getProviderName() */ class SnakeCaseDto extends Dto { protected int $actualNumber; protected string $providerName; } $data = [ 'actualNumber' => 5, 'providerName' => 'Main Provider', ]; $dto = new SnakeCaseDto($data); $array = $dto->toArray(); // ['actualNumber' => 5, 'providerName' => 'Main Provider'] $arrayWithSnakeCaseKeys = $dto->toArray(KeyCase::SNAKE_CASE); // ['actual_number' => 5, 'provider_name' => 'Main Provider']
For developers
Requirements
Utils:
- make
- docker-compose
Setup
Initialize
Create ./docker/.env
make init
Build container with the different php version
php 8.1
make up81
php 8.2
make up82
php 8.3
make up83
Also you need to run this command before build container with another php version. It will remove network and previously created container.
make down
Other commands
Go inside of the container
make inside
Check php version
make php-v
Check package version
make v
Run tests and linters
Run PHPUnit tests with code coverage
make test-c
Run Psalm
make psalm
Run PHP_CodeSniffer
make phpcs
Or by all-in-one command from the inside of the container
composer check-all
License
The php-dto library is open-sourced software licensed under the MIT license.