PHP Classes

PHP Plain Object with Class Variables Set from Array Values: Initialize data objects from arrays of values

Recommend this page to a friend!
  Info   View files Documentation   View files View files (109)   DownloadInstall with Composer Download .zip   Reputation   Support forum (1)   Blog (1)    
Last Updated Ratings Unique User Downloads Download Rankings
2023-06-15 (1 month ago) RSS 2.0 feedNot enough user ratingsTotal: 31 All time: 10,830 This week: 21Up
Version License PHP version Categories
plain-to-class 1.0MIT/X Consortium ...7Language, PHP 7
Description 

Author

Andey Iatsenko


Contributor

This package can initialize data objects from arrays of values.

It can take a class identifier and creates a new class object.

The package can also initialize the created object variables with values from an array.

Under PHP 8 or a more recent version, the package initializes the object variables using values passed as named arguments to this package's create function.

Innovation Award
PHP Programming Innovation award nominee
June 2023
Number 6
Hydration is the process of initializing an object variable using values obtained separately.

A hydration class can, for instance, take an associative array, traverse the array values and assign class variables with the values of the array entries that have the same key value as the class variable name.

This package allows hydrating of an object from an associate array with the class variable values.

If you run PHP 8 or later, the package can hydrate an object of named argument values. This way, the object creation and initialization can be done using a single line of readable PHP code.

Manuel Lemos
Picture of Andrey Iatsenko
  Performance   Level  
Name: Andrey Iatsenko <contact>
Classes: 2 packages by
Country: Russian Federation Russian Federation
Innovation award
Innovation award
Nominee: 2x

Details

ClassTransformer

Packagist Version GitHub Workflow Status (with branch) Coverage License readthedocs Packagist Downloads Packagist Downloads

Mutation testing badge type-coverage psalm-level

> Alas, I do not speak English, and the documentation was compiled through google translator :( I will be glad if you can help me describe the documentation more correctly :)

This library will allow you to easily convert any data set into the object you need. You are not required to change the structure of classes, inherit them from external modules, etc. No dancing with tambourines - just data and the right class.

It is considered good practice to write code independent of third-party packages and frameworks. The code is divided into services, domain zones, various layers, etc.

To transfer data between layers, the DataTransfer Object (DTO) template is usually used. A DTO is an object that is used to encapsulate data and send it from one application subsystem to another.

Thus, services/methods work with a specific object and the data necessary for it. At the same time, it does not matter where this data was obtained from, it can be an http request, a database, a file, etc.

Accordingly, each time the service is called, we need to initialize this DTO. But it is not effective to compare data manually each time, and it affects the readability of the code, especially if the object is complex.

This is where this package comes to the rescue, which takes care of all the work with mapping and initialization of the necessary DTO.

Documentation

Installation

The package can be installed via composer:

composer require yzen.dev/plain-to-class

> Note: The current version of the package supports only PHP 8.0 +.

> For PHP version 7.4, you can read the documentation in version v0.*.

Usage

Common use case:

Base

namespace DTO;

class CreateUserDTO
{
    public string $email;
    public float $balance;
}

$data = [
    'email' => 'test@mail.com',
    'balance' => 128.41,
];

$dto = (new Hydrator())->create(CreateUserDTO::class, $data);
// or static init        
$dto = Hydrator::init()->create(CreateUserDTO::class, $data);
var_dump($dto);

Result:

object(\LoginDTO)
  'email' => string(13) "test@mail.com"
  'balance' => float(128.41) 

Also for php 8 you can pass named arguments:

$dto = Hydrator::init()->create(CreateUserDTO::class,
        email: 'test@mail.com',
        balance: 128.41
      );

If the property is not of a scalar type, but a class of another DTO is allowed, it will also be automatically converted.

class ProductDTO
{
    public int $id;
    public string $name;
}

class PurchaseDTO
{
    public ProductDTO $product;
    public float $cost;
}

$data = [
    'product' => ['id' => 1, 'name' => 'phone'],
    'cost' => 10012.23,
];

$purchaseDTO = Hydrator::init()->create(PurchaseDTO::class, $data);
var_dump($purchaseDTO);

Output:

object(PurchaseDTO)
  public ProductDTO 'product' => 
    object(ProductDTO)
      public int 'id' => int 1
      public string 'name' => string 'phone' (length=5)
  public float 'cost' => float 10012.23

Collection

If you have an array of objects of a certain class, then you must specify the ConvertArray attribute for it, passing it to which class you need to bring the elements.

You can also specify a class in PHP DOC, but then you need to write the full path to this class array <\DTO\ProductDTO>. This is done in order to know exactly which instance you need to create. Since Reflection does not provide out-of-the-box functions for getting the use * file. Besides use *, you can specify an alias, and it will be more difficult to trace it. Example:


class ProductDTO
{
    public int $id;
    public string $name;
}

class PurchaseDTO
{
    #[ConvertArray(ProductDTO::class)]
    public array $products;
}

$data = [
    'products' => [
        ['id' => 1, 'name' => 'phone',],
        ['id' => 2, 'name' => 'bread',],
    ],
];
$purchaseDTO = Hydrator::init()->create(PurchaseDTO::class, $data);

Anonymous array

In case you need to convert an array of data into an array of class objects, you can implement this using the transformCollection method.

$data = [
  ['id' => 1, 'name' => 'phone'],
  ['id' => 2, 'name' => 'bread'],
];
$products = Hydrator::init()->createCollection(ProductDTO::class, $data);

As a result of this execution, you will get an array of ProductDTO objects

array(2) {
  [0]=>
      object(ProductDTO) {
        ["id"]=> int(1)
        ["name"]=> string(5) "phone"
      }
  [1]=>
      object(ProductDTO) {
        ["id"]=> int(2)
        ["name"]=> string(5) "bread"
      }
} 

You may also need a piecemeal transformation of the array. In this case, you can pass an array of classes, which can then be easily unpacked.

    $userData = ['id' => 1, 'email' => 'test@test.com', 'balance' => 10012.23];
    $purchaseData = [
        'products' => [
            ['id' => 1, 'name' => 'phone',],
            ['id' => 2, 'name' => 'bread',],
        ],
        'user' => ['id' => 3, 'email' => 'fake@mail.com', 'balance' => 10012.23,],
    ];

    $result = Hydrator::init()->createMultiple([UserDTO::class, PurchaseDTO::class], [$userData, $purchaseData]);
    
    [$user, $purchase] = $result;
    var_dump($user);
    var_dump($purchase);

Result:

object(UserDTO) (3) {
  ["id"] => int(1)
  ["email"]=> string(13) "test@test.com"
  ["balance"]=> float(10012.23)
}

object(PurchaseDTO) (2) {
  ["products"]=>
  array(2) {
    [0]=>
    object(ProductDTO)#349 (3) {
      ["id"]=> int(1)
      ["name"]=> string(5) "phone"
    }
    [1]=>
    object(ProductDTO)#348 (3) {
      ["id"]=> int(2)
      ["name"]=> string(5) "bread"
    }
  }
  ["user"]=>
  object(UserDTO)#332 (3) {
    ["id"]=> int(3)
    ["email"]=> string(13) "fake@mail.com"
    ["balance"]=> float(10012.23)
  }
}

Writing style

A constant problem with the style of writing, for example, in the database it is snake_case, and in the camelCase code. And they constantly need to be transformed somehow. The package takes care of this, you just need to specify the WritingStyle attribute on the property:

class WritingStyleSnakeCaseDTO
{
    #[WritingStyle(WritingStyle::STYLE_CAMEL_CASE, WritingStyle::STYLE_SNAKE_CASE)]
    public string $contact_fio;

    #[WritingStyle(WritingStyle::STYLE_CAMEL_CASE)]
    public string $contact_email;
}


 $data = [
  'contactFio' => 'yzen.dev',
  'contactEmail' => 'test@mail.com',
];
$model = Hydrator::init()->create(WritingStyleSnakeCaseDTO::class, $data);
var_dump($model);

RESULT:

object(WritingStyleSnakeCaseDTO) (2) {
  ["contact_fio"]=> string(8) "yzen.dev"
  ["contact_email"]=> string(13) "test@mail.com"
}

Alias

Various possible aliases can be set for the property, which will also be searched in the data source. This can be useful if the DTO is generated from different data sources.

class WithAliasDTO
{
    #[FieldAlias('userFio')]
    public string $fio;

    #[FieldAlias(['email', 'phone'])]
    public string $contact;
}

Custom setter

If a field requires additional processing during its initialization, you can mutator. To define a mutator, define a set{Attribute}Attribute method on your class where {Attribute} is cased name of the property you wish to access. This mutator will be automatically called when we attempt to set the value of the real_address attribute on the model:

class UserDTO
{
    public int $id;
    public string $real_address;

    public function setRealAddressAttribute(string $value)
    {
        $this->real_address = strtolower($value);
    }
}

After Transform

Inside the class, you can create the afterTransform method, which will be called immediately after the conversion is completed. In it, we can describe our additional verification or transformation logic by already working with the state of the object.

class UserDTO
{
    public int $id;
    public float $balance;

    public function afterTransform()
    {
        $this->balance = 777;
    }
}

Custom transform

If you need to completely transform yourself, then you can create a transform method in the class. In this case, no library processing is called, all the responsibility of the conversion passes to your class.

class CustomTransformUserDTOArray
{
    public string $email;
    public string $username;
    
    public function transform($args)
    {
        $this->email = $args['login'];
        $this->username = $args['fio'];
    }
}

Cache

The package supports a class caching mechanism to avoid the cost of reflection. This functionality is recommended to be used only if you have very voluminous classes, or there is a cyclic transformation of multiple entities. On ordinary lightweight DTO, there will be only 5-10%, and this will be unnecessary access in the file system.

You can enable caching by passing the config to the hydrator constructor:

(new Hydrator(new HydratorConfig(true)))
    ->create(PurchaseDto::class, $data);

Comparison

I also made a comparison with current analogues and here are the main disadvantages - Works only for a specific framework - Force to inherit or change your current class structure - Conversion takes longer

Below is an example of my benchmark comparison

https://github.com/yzen-dev/php-dto-transform-benchmark image

  Files folder image Files  
File Role Description
Files folder image.github (1 directory)
Files folder imagebin (2 files)
Files folder imagedocs (3 files)
Files folder imagesrc (8 files, 7 directories)
Files folder imagetests (1 file, 3 directories)
Accessible without login Plain text file .editorconfig Data Auxiliary data
Accessible without login Plain text file composer.json Data Auxiliary data
Accessible without login Plain text file composer.lock Data Auxiliary data
Accessible without login Plain text file infection.json.dist Data Auxiliary data
Accessible without login Plain text file phpbench.json Data Auxiliary data
Accessible without login Plain text file phpcs.xml Data Auxiliary data
Accessible without login Plain text file phpunit.xml Data Auxiliary data
Accessible without login Plain text file psalm.xml Data Auxiliary data
Accessible without login Plain text file README.md Doc. Documentation
Accessible without login Plain text file README.RU.md Doc. Documentation

  Files folder image Files  /  .github  
File Role Description
Files folder imageworkflows (4 files)

  Files folder image Files  /  .github  /  workflows  
File Role Description
  Accessible without login Plain text file cs.yml Data Auxiliary data
  Accessible without login Plain text file mutation.yml Data Auxiliary data
  Accessible without login Plain text file psalm.yml Data Auxiliary data
  Accessible without login Plain text file tests.yml Data Auxiliary data

  Files folder image Files  /  bin  
File Role Description
  Accessible without login Plain text file plain-to-class-clear Data Auxiliary data
  Accessible without login Plain text file plain-to-class-clear.bat Data Auxiliary data

  Files folder image Files  /  docs  
File Role Description
  Accessible without login Plain text file index.rst Data Auxiliary data
  Accessible without login Plain text file installation.rst Data Auxiliary data
  Accessible without login Plain text file usage.rst Data Auxiliary data

  Files folder image Files  /  src  
File Role Description
Files folder imageAttributes (4 files)
Files folder imageCacheGenerator (1 file)
Files folder imageContracts (2 files)
Files folder imageEnums (1 file)
Files folder imageExceptions (4 files)
Files folder imageReflection (4 files, 1 directory)
Files folder imageValidators (1 file)
  Plain text file ArgumentsRepository.php Class Class source
  Plain text file ClassRepository.php Class Class source
  Plain text file ClassTransformer.php Class Class source
  Plain text file Hydrator.php Class Class source
  Plain text file HydratorConfig.php Class Class source
  Plain text file InstanceBuilder.php Class Class source
  Plain text file TransformUtils.php Class Class source
  Plain text file ValueCasting.php Class Class source

  Files folder image Files  /  src  /  Attributes  
File Role Description
  Plain text file ConvertArray.php Class Class source
  Plain text file FieldAlias.php Class Class source
  Plain text file NotTransform.php Class Class source
  Plain text file WritingStyle.php Class Class source

  Files folder image Files  /  src  /  CacheGenerator  
File Role Description
  Plain text file CacheGenerator.php Class Class source

  Files folder image Files  /  src  /  Contracts  
File Role Description
  Plain text file ReflectionClassRepository.php Class Class source
  Plain text file ReflectionProperty.php Class Class source

  Files folder image Files  /  src  /  Enums  
File Role Description
  Plain text file TypeEnums.php Class Class source

  Files folder image Files  /  src  /  Exceptions  
File Role Description
  Plain text file ClassNotFoundException.php Class Class source
  Plain text file InstantiableClassException.php Class Class source
  Plain text file InvalidArgumentException.php Class Class source
  Plain text file ValueNotFoundException.php Class Class source

  Files folder image Files  /  src  /  Reflection  
File Role Description
Files folder imageTypes (6 files)
  Plain text file CacheReflectionClass.php Class Class source
  Plain text file CacheReflectionProperty.php Class Class source
  Plain text file RuntimeReflectionClass.php Class Class source
  Plain text file RuntimeReflectionProperty.php Class Class source

  Files folder image Files  /  src  /  Reflection  /  Types  
File Role Description
  Plain text file ArrayType.php Class Class source
  Plain text file EnumType.php Class Class source
  Plain text file PropertyType.php Class Class source
  Plain text file PropertyTypeFactory.php Class Class source
  Plain text file ScalarType.php Class Class source
  Plain text file TransformableType.php Class Class source

  Files folder image Files  /  src  /  Validators  
File Role Description
  Plain text file ClassExistsValidator.php Class Class source

  Files folder image Files  /  tests  
File Role Description
Files folder imageBenchmark (1 file, 1 directory)
Files folder imageIntegration (11 files, 1 directory)
Files folder imageUnits (8 files, 1 directory)
  Plain text file ClearCache.php Class Class source

  Files folder image Files  /  tests  /  Benchmark  
File Role Description
Files folder imageBid (2 files, 1 directory)
  Plain text file SerializeVsArrayBench.php Class Class source

  Files folder image Files  /  tests  /  Benchmark  /  Bid  
File Role Description
Files folder imageDto (4 files, 1 directory)
  Plain text file FullCheckBench.php Class Class source
  Plain text file ManyCheckBench.php Class Class source

  Files folder image Files  /  tests  /  Benchmark  /  Bid  /  Dto  
File Role Description
Files folder imageAddress (2 files)
  Plain text file ProductDto.php Class Class source
  Plain text file PurchaseDto.php Class Class source
  Plain text file UserDto.php Class Class source
  Accessible without login Plain text file UserTypeEnum.php Aux. Auxiliary script

  Files folder image Files  /  tests  /  Benchmark  /  Bid  /  Dto  /  Address  
File Role Description
  Plain text file AddressClean.php Class Class source
  Plain text file MetroDto.php Class Class source

  Files folder image Files  /  tests  /  Integration  
File Role Description
Files folder imageDTO (25 files)
  Plain text file AfterTransformTest.php Class Class source
  Plain text file ClassTransformerExceptionsTest.php Class Class source
  Plain text file ClassTransformerFromArrayTest.php Class Class source
  Plain text file ClassTransformerFromCacheTest.php Class Class source
  Plain text file ClassTransformerFromObjectTest.php Class Class source
  Plain text file CustomSetterAttributeTest.php Class Class source
  Plain text file CustomTransformerTest.php Class Class source
  Plain text file EnumTest.php Class Class source
  Plain text file FakerData.php Class Class source
  Plain text file NotTransformTest.php Class Class source
  Plain text file WritingStyleTest.php Class Class source

  Files folder image Files  /  tests  /  Integration  /  DTO  
File Role Description
  Plain text file ArrayScalarDTO.php Class Class source
  Plain text file BasketDTO.php Class Class source
  Accessible without login Plain text file ColorEnum.php Aux. Auxiliary script
  Accessible without login Plain text file ColorScalarEnum.php Aux. Auxiliary script
  Plain text file ConstructDto.php Class Class source
  Plain text file CustomSetterAttibuteDTO.php Class Class source
  Plain text file CustomTransformUserDTO.php Class Class source
  Plain text file CustomTransformUserDTOArray.php Class Class source
  Plain text file EmptyClassDto.php Class Class source
  Plain text file ExampleWithEnumDTO.php Class Class source
  Plain text file FakeClassDTO.php Class Class source
  Plain text file ProductDTO.php Class Class source
  Plain text file PurchaseDTO.php Class Class source
  Plain text file PurchaseForCacheDto.php Class Class source
  Plain text file UserAfterTransformDTO.php Class Class source
  Plain text file UserCacheableDTO.php Class Class source
  Plain text file UserDTO.php Class Class source
  Plain text file UserEmptyTypeDTO.php Class Class source
  Plain text file UserNotTransformDTO.php Class Class source
  Plain text file UserNotTransformRelationDTO.php Class Class source
  Plain text file UserNoTypeArrayDTO.php Class Class source
  Plain text file WithAliasDTO.php Class Class source
  Plain text file WritingStyleCamelCaseDTO.php Class Class source
  Plain text file WritingStyleEmpyDTO.php Class Class source
  Plain text file WritingStyleSnakeCaseDTO.php Class Class source

  Files folder image Files  /  tests  /  Units  
File Role Description
Files folder imageDTO (5 files)
  Plain text file ArgumentsResourceTest.php Class Class source
  Plain text file CacheGeneratorTest.php Class Class source
  Plain text file ClassExistsValidatorTest.php Class Class source
  Plain text file PropertyTypeFactoryTest.php Class Class source
  Plain text file RuntimeReflectionClassTest.php Class Class source
  Plain text file RuntimeReflectionPropertyTest.php Class Class source
  Plain text file TransformUtilsTest.php Class Class source
  Plain text file ValueCastingTest.php Class Class source

  Files folder image Files  /  tests  /  Units  /  DTO  
File Role Description
  Plain text file AbstractClass.php Class Class source
  Accessible without login Plain text file ColorEnum.php Aux. Auxiliary script
  Plain text file ExtendedDto.php Class Class source
  Plain text file UserCacheableDTO.php Class Class source
  Plain text file UserDTO.php Class Class source

 Version Control Unique User Downloads Download Rankings  
 100%
Total:31
This week:0
All time:10,830
This week:21Up
User Comments (1)