PHPackages                             salamov/dto-hydrator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. salamov/dto-hydrator

ActiveSymfony-bundle[API Development](/categories/api)

salamov/dto-hydrator
====================

Dynamic Hydration For Dto's Transformers in API Platform

1.0.2(6y ago)02[1 PRs](https://github.com/omarfawzi/DTO-Hydrator/pulls)MITPHPPHP &gt;=7.2

Since Nov 13Pushed 3y ago1 watchersCompare

[ Source](https://github.com/omarfawzi/DTO-Hydrator)[ Packagist](https://packagist.org/packages/salamov/dto-hydrator)[ RSS](/packages/salamov-dto-hydrator/feed)WikiDiscussions master Synced today

READMEChangelog (1)Dependencies (8)Versions (5)Used By (0)

[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Latest Stable Version](https://camo.githubusercontent.com/2c0966162353b7a7d7213a20a2445813ab55ef5bc0d3e580d867d8d951622fe0/68747470733a2f2f706f7365722e707567782e6f72672f73616c616d6f762f64746f2d6879647261746f722f762f737461626c65)](https://packagist.org/packages/salamov/dto-hydrator)[![Total Downloads](https://camo.githubusercontent.com/857aac54fec4e75609e0cbf06d95116c317f3675e1fba2f6492809c34d3262ee/68747470733a2f2f706f7365722e707567782e6f72672f73616c616d6f762f64746f2d6879647261746f722f646f776e6c6f616473)](https://packagist.org/packages/salamov/dto-hydrator)

Description
===========

[](#description)

Dynamic Hydration for DTO's used by Transformers in [API Platform](https://api-platform.com) .

Install
-------

[](#install)

`composer require salamov/dto-hydrator`

Usage
-----

[](#usage)

While using API Platform , using custom DTO's (defining custom input/output in the `@ApiResource`) requires you to deal with custom transformers specially when your DTO represents an Entity .

1. When using an input transformer **i.e : after the request body is denormalized into a DTO** , you should dehydrate the DTO **i.e** transform it to an entity in order to be persisted .
2. When using an output transformer **i.e : after the entity is retrieved and waiting to be normalized** , you should hydrate the DTO **i.e** transform the entity into a DTO in order to be displayed .
3. The embedded objects inside the Dto must be an `@ApiResource` in order to generate the swagger documentation
4. If the embedded objects defines `id` within the denormalized request body it will be referenced and the data will be updated , either it will be persisted as a new `Entity`.

Example
-------

[](#example)

```
use Symfony\Component\Serializer\Annotation\Groups;

class OrderDto {

    /**
     * @var integer $id
     * @Groups({"order:read","order:put"})
     */
    protected $id;

    /**
     * @var Customer $customer
     * @Groups({"order:read","order:put"})
     */
    protected $customer;

    /**
     * @var Product[] $products
     * @Groups({"order:read","order:put"})
     */
    protected $products;

    /**
     * @return int
    */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @param int $id
    */
    public function setId(int $id)
    {
        $this->id = $id;
    }

    /**
     * @return Customer
    */
    public function getCustomer(): Customer
    {
        return $this->customer;
    }

    /**
     * @param Customer $customer
    */
    public function setCustomer(Customer $customer)
    {
        $this->customer = $customer;
    }

    /**
     * @return Product[]
    */
    public function getProducts(): array
    {
        return $this->products;
    }

    /**
     * @param Product[] $products
    */
    public function setProducts(array $products)
    {
        $this->products = $products;
    }
}

```

```
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiProperty;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table
 * @ORM\Entity
 * @ApiResource(
 *     itemOperations={
 *        "get":{
 *           "method":"get",
 *           "input":false,
 *           "output":OrderDto::class,
 *           "status":200,
 *           "normalization_context":{"groups":{"order:read"}}
 *        },
 *        "put":{
 *           "method":"put",
 *           "input":OrderDto::class,
 *           "output":OrderDto::class,
 *           "status":200,
 *           "denormalization_context":{"groups":{"order:put"}},
 *           "normalization_context":{"groups":{"order:read"}}
 *        }
 *     },
 *     collectionOperations={}
 * )
*/
class Order {
    /**
    * @var integer
    *
    * @ORM\Column(name="id", type="integer", nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="IDENTITY")
    * @ApiProperty(identifier=true)
    */
   protected $id;

    /**
     * @var Customer $customer
     * @ORM\ManyToOne(targetEntity="Customer",cascade={"persist"})
     * @ORM\JoinColumn(name="customerId", referencedColumnName="id")
     */
    protected $customer;

   /**
   * @var Product[] $products
   * @ORM\OneToMany(targetEntity="Product",cascade={"persist"})
   */
   protected $products;

    /**
     * @return int
    */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @param int $id
    */
    public function setId(int $id)
    {
        $this->id = $id;
    }

    /**
     * @return Customer
    */
    public function getCustomer(): Customer
    {
        return $this->customer;
    }

    /**
     * @param Customer $customer
    */
    public function setCustomer(Customer $customer)
    {
        $this->customer = $customer;
    }

    /**
     * @return Product[]
    */
    public function getProducts(): array
    {
        return $this->products;
    }

    /**
     * @param Product[] $products
    */
    public function setProducts(array $products)
    {
        $this->products = $products;
    }
}

```

Above we defined an `OrderDto` for the `Order` Entity with two embedded objects `Customer` and `Products` one is related to `Order` by a `ManyToOne` relations ship and the other is related to `Order` by a `OneToMany` relationship.

### GET Request

[](#get-request)

```
 GET https://domain.com/api/orders/{id}

```

The above request will go first through your custom dataProvider (if you have one) retrieving the `Order` Entity to be transformed and normalized , if you defined an `Ouput` for your `@ApiResource`then you should define a transformer your transformer would look like this :

```
use DtoHydrator\Factory\DtoDtoFactory;
use DtoHydrator\Dto\Hydrator;

class OrderDtoOutputTransformer {

    /** @var DtoFactory $factory */
    protected $factory;

    /**
     * OrderDtoOutputTransformer constructor.
     *
     * @param DtoFactory $factory
     */
    public function __construct(DtoFactory $factory) { $this->factory = $factory; }

    /**
     * Checks whether the transformation is supported for a given data and context.
     *
     * @param object|array $data object on normalize / array on denormalize
     * @param string       $to
     * @param array        $context
     * @return bool
     */
    public function supportsTransformation($data, string $to, array $context = []): bool
    {
        return OrderDto::class === $to && $data instanceof Order;
    }

    /**
     * Transforms the given object to something else, usually another object.
     * This must return the original object if no transformation has been done.
     *
     * @param Order $order
     *
     * @param string          $to
     * @param array           $context
     * @return OrderDto
     */
    public function transform($order, string $to, array $context = []): OrderDto
    {
        $orderDto = new OrderDto();

        $this->factory->make(Hydrator::class)->hydrate($order,$orderDto,$context);

        return $orderDto;
    }

}

```

### PUT Request

[](#put-request)

```
 PUT https://domain.com/api/orders/{id}

 body={
     id:1,
     customer:{
        id:1,
        fname:"Omar",
        lnaem:"Salamov"
     },
     products:[
       {
          id:10,
          name:"Long Sleeves",
          brand: "Gap"
       },
       {
         id:11,
         name:"Short Sleves",
         brand: "H&M"
       }
    ]
 }

```

The above request will be denormalized to your `Input` class defined in the `@ApiResource`then to your `InputTransformer` in order to be transformed to an `Entity` and persisted , so your `InputTransformer`would look like this :

```
use DtoHydrator\Factory\DtoDtoFactory;
use DtoHydrator\Dto\Dehydrator;
use Doctrine\ORM\EntityManagerInterface;

class OrderDtoInputTransformer {

    /** @var DtoFactory $factory */
    protected $factory;

    /** @var EntityManagerInterface $entityManager */
    protected $entityManager;

    /**
     * OrderDtoInputTransformer constructor.
     *
     * @param DtoFactory                $factory
     * @param EntityManagerInterface $entityManager
     */
    public function __construct(DtoFactory $factory, EntityManagerInterface $entityManager)
    {
        $this->factory       = $factory;
        $this->entityManager = $entityManager;
    }

    /**
     * Checks whether the transformation is supported for a given data and context.
     *
     * @param object|array $data object on normalize / array on denormalize
     * @param string       $to
     * @param array        $context
     * @return bool
     */
    public function supportsTransformation($data, string $to, array $context = []): bool
    {
        return Order::class === $to && in_array('order:put',$context['groups']);
    }

    /**
     * Transforms the given object to something else, usually another object.
     * This must return the original object if no transformation has been done.
     *
     * @param OrderDto  $order
     * @param string    $to
     * @param array     $context
     * @return Order
     * @throws Throwable
     */
    public function transform($orderDto, string $to, array $context = []): Order
    {
        /** @var Order $order */
        $order = $this->entityManager->getReference(Order::class, $orderDto->getId());

        // in case you are creating a new order
        // you will need to instantiate a new instance from order instead of referencing

        $this->factory->make(Dehydrator::class)->hydrate($orderDto,$order,$context);

        return $order;
    }
}

```

**N.B :** If your body/embedded body contains an `id` it will be directly referenced to the corresponding entity for that `id` and the data will be updated , if not it will be created .

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity2

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 89.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

3

Last Release

2368d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8095037?v=4)[Omar Mohamed](/maintainers/omarfawzi)[@omarfawzi](https://github.com/omarfawzi)

---

Top Contributors

[![omarfawzi](https://avatars.githubusercontent.com/u/8095037?v=4)](https://github.com/omarfawzi "omarfawzi (17 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

apiapi-platformsymfony-bundle

### Embed Badge

![Health badge](/badges/salamov-dto-hydrator/health.svg)

```
[![Health](https://phpackages.com/badges/salamov-dto-hydrator/health.svg)](https://phpackages.com/packages/salamov-dto-hydrator)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
