Simple abstraction for object transformations., (*1)
, (*2)
Installation
Require dependencies via composer:
$ composer require tonicforhealth/model-transformer
Usage
Possible use cases:, (*3)
- Separate domain model layer from view or presentation layer, but still keep objects.
- Separate domain model from resource representations (in RESTful applications).
Suppose, there are two domain objects:, (*4)
<?php
class Product
{
/**
* @var string
*/
private $name;
/**
* @var Category
*/
private $category;
// ...
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return Category
*/
public function getCategory()
{
return $this->category;
}
}
class Category
{
/**
* @var string
*/
private $name;
// ...
/**
* @return string
*/
public function getName()
{
return $this->name;
}
}
And one presentation object which can be used in presentation layer:, (*5)
<?php
class ProductPresentation
{
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $categoryName;
/**
* @var int
*/
private $purchasedCount;
// ...
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return string
*/
public function getCategoryName()
{
return $this->categoryName;
}
/**
* @return string
*/
public function getPurchasedCount()
{
return $this->purchased;
}
}
There are lot of solutions for transforming Product and Category objects to ProductRepresentation:, (*6)
- just create
ProductRepresentation based Product and Category on at the needed place;
- create factory for
ProductRepresentation;
- and so on.
This library provides simple and concise solution for this problem:, (*7)
- Create transformer for objects.
- Register it in transformer manager or use it separately.
Possible transformer for ProductRepresentation:, (*8)
<?php
class ProductToProductRepresentationModelTransformer implements ModelTransformerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
// ...
/**
* {@inheritdoc}
*/
public function supports($object, $targetClass)
{
return ($object instanceof Product) && is_a($targetClass, ProductRepresentation::class, true);
}
/**
* {@inheritdoc}
*/
public function transform($object, $targetClass)
{
/** @var Product $product */
$product = $object;
$purchasedCount = $this->productRepository->computePurchasedCount($product);
return new ProductRepresentation(
$product->getName(),
$product->getCategory()->getName(),
$purchasedCount
);
}
}
Register it:, (*9)
<?php
$priority = 0;
$modelTransformer->addTransformer($productToProductRepresentationModelTransformer, $priority = 0);
With an optional priority integer (higher equals more important and therefore that the transformer will be triggered earlier)
that determines when a transformer is triggered versus other transformers (defaults to 0)., (*10)
Use it anywhere:, (*11)
<?php
$productRepresentation = $modelTransformer->transform($product, ProductRepresentation::class);
If you have simple rules of transformation, you can use ObjectTransformerInterface instead. As bonus
transformation will work much faster., (*12)
Specifications
All actual documentation is runnable library specifications at /spec directory., (*13)
And to ensure library is not broken, run (under library directory):, (*14)
bin/phpspec run