PHPackages                             entelisteam/lbaf-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. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. entelisteam/lbaf-hydrator

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

entelisteam/lbaf-hydrator
=========================

Attribute-driven PHP DTO hydrator: builds typed DTOs, enums, nested objects and typed arrays from JSON-like data.

1.4.2(3w ago)026MITPHPPHP ~8.2

Since May 12Pushed 3w agoCompare

[ Source](https://github.com/entelisteam/lbaf-hydrator)[ Packagist](https://packagist.org/packages/entelisteam/lbaf-hydrator)[ RSS](/packages/entelisteam-lbaf-hydrator/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (8)Versions (6)Used By (0)

entelisteam/lbaf-hydrator
=========================

[](#entelisteamlbaf-hydrator)

Attribute-driven PHP DTO hydrator. Builds typed DTOs (and arrays of DTOs) from JSON-like data — scalars, enums, nested objects, union types, `DateTime`.

Install
-------

[](#install)

```
composer require entelisteam/php-dto-hydrator
```

Requires PHP 8.2 or newer. Depends on [`entelisteam/php-reflection-helpers`](https://packagist.org/packages/entelisteam/php-reflection-helpers).

Quick start
-----------

[](#quick-start)

Добавьте `HydratorTrait` в свой DTO — и получите статические методы для гидратации из массивов и объектов:

```
use EntelisTeam\Lbaf\Hydrator\HydratorTrait;

class UserDTO {
    use HydratorTrait;

    public function __construct(
        public readonly int $id,
        public readonly string $name,
        public readonly ?string $email = null,
    ) {}
}

$user = UserDTO::hydrateObject([
    'id'    => '42',        // приведётся к int
    'name'  => 'Alice',
    'email' => 'a@b.com',
]);
```

Современные IDE подхватывают методы трейта автоматически — `implements HydratorInterface` имплементировать не нужно.

Массив DTO
----------

[](#массив-dto)

```
$users = UserDTO::hydrateArray([
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
]);
```

Второй аргумент `hydrateArray($data, skipErrors: true)` пропускает невалидные элементы вместо того, чтобы кидать исключение на первой же ошибке.

Вложенные объекты
-----------------

[](#вложенные-объекты)

Типы вложенных DTO определяются по `__construct` — никаких дополнительных атрибутов для них не нужно:

```
class AddressDTO {
    use HydratorTrait;

    public function __construct(
        public readonly string $city,
        public readonly string $street,
    ) {}
}

class CustomerDTO {
    use HydratorTrait;

    public function __construct(
        public readonly int $id,
        public readonly AddressDTO $address,
    ) {}
}

$customer = CustomerDTO::hydrateObject([
    'id'      => 1,
    'address' => ['city' => 'Berlin', 'street' => 'Unter den Linden'],
]);
```

Массивы DTO внутри DTO через `#[ArrayTypeOf]`
---------------------------------------------

[](#массивы-dto-внутри-dto-через-arraytypeof)

PHP-тип `array` не несёт информации об элементах — для типизированных коллекций используйте атрибут:

```
use EntelisTeam\Lbaf\Hydrator\Attribute\ArrayTypeOf;

class LineItemDTO {
    use HydratorTrait;

    public function __construct(
        public readonly string $sku,
        public readonly int $qty,
    ) {}
}

class OrderDTO {
    use HydratorTrait;

    public function __construct(
        public readonly int $id,
        #[ArrayTypeOf('items', LineItemDTO::class)]
        public readonly array $items,
    ) {}
}

$order = OrderDTO::hydrateObject([
    'id'    => 100,
    'items' => [
        ['sku' => 'A-1', 'qty' => 2],
        ['sku' => 'B-7', 'qty' => 1],
    ],
]);
```

Каждый элемент `items` будет построен как `LineItemDTO`.

Переименование полей через `#[Map]`
-----------------------------------

[](#переименование-полей-через-map)

Когда имя свойства DTO отличается от ключа во входных данных (snake\_case → camelCase, legacy-схемы, чужие API), используйте `#[Map()]`:

```
use EntelisTeam\Lbaf\Hydrator\Attribute\Map;

class UserDTO {
    use HydratorTrait;

    #[Map('user_id')]
    public readonly int $userId;

    #[Map('full_name')]
    public readonly string $fullName;
}

$user = UserDTO::hydrateObject([
    'user_id'   => 42,
    'full_name' => 'Alice Doe',
]);
```

Атрибут работает и на параметрах конструктора (в том числе promoted):

```
class CustomerDTO {
    use HydratorTrait;

    public function __construct(
        #[Map('customer_id')]   public readonly int $id,
        #[Map('shipping_city')] public readonly string $city,
    ) {}
}
```

Если ключа из `#[Map]` нет во входных данных — поле получит значение по умолчанию (или будет выброшен `RequiredArgumentException`, если default отсутствует и тип не nullable). Путь в сообщении ошибки имеет вид `propName{mappedKey}`, чтобы было видно и имя свойства, и имя ключа.

### Несколько источников данных

[](#несколько-источников-данных)

Если один и тот же DTO собирается из разных схем (например, legacy- и новый API), можно навесить несколько `#[Map]` с разными `source` и передать нужный источник в гидратор:

```
class UserDTO {
    use HydratorTrait;

    #[Map('user_id', 'legacy')]
    #[Map('id', 'v2')]
    public readonly int $userId;

    #[Map('full_name', 'legacy')]
    #[Map('name', 'v2')]
    public readonly string $fullName;
}

$fromLegacy = UserDTO::hydrateObject(
    ['user_id' => 42, 'full_name' => 'Alice Doe'],
    source: 'legacy',
);

$fromV2 = UserDTO::hydrateObject(
    ['id' => 42, 'name' => 'Alice Doe'],
    source: 'v2',
);
```

Правила резолва:

- Если `source` передан в гидратор то берется Map(source) ?? Map(null) ?? имя свойства
- Если `source` не передан в гидратор то берется Map(null) ?? имя свойства

`source` пробрасывается во вложенные DTO и элементы массивов автоматически.

Что умеет гидратор
------------------

[](#что-умеет-гидратор)

- Скаляры с приведением типов (`"42"` → `int 42`).
- `enum` и `BackedEnum` — по значению.
- `DateTime` / `DateTimeImmutable` — из строки или таймстампа.
- Вложенные DTO и массивы DTO (через `#[ArrayTypeOf]`).
- Union-типы — выбирается первый совместимый по структуре вариант.
- Дефолтные значения из `__construct` — если поля нет во входных данных.
- Переименование полей через `#[Map]` — для несовпадающих с DTO ключей во входных данных.

Кэш гидраторов
--------------

[](#кэш-гидраторов)

`HydratorTrait::getHydrator()` отдаёт `Hydrator` из `HydratorRegistry` — на класс создаётся ровно один экземпляр за процесс, парсинг рефлексии не повторяется. Никакой ручной настройки не требуется.

Исключения
----------

[](#исключения)

Все ошибки гидратации наследуются от `EntelisTeam\DTOHydrator\Exception\HydrationException`:

- `RequiredArgumentException` — обязательное поле отсутствует во входных данных.
- `ArgumentTypeException` — значение нельзя привести к объявленному типу.

Оба исключения несут JSON-путь до проблемного поля, чтобы сообщение об ошибке сразу указывало место.

Версионирование
---------------

[](#версионирование)

Все пакеты LBAF следуют [SemVer](https://semver.org):

- **Major (`1.x` → `2.0`)** — слом обратной совместимости публичного API. Каждое такое изменение сопровождается Rector-миграцией (см. [lbaf-rector](https://github.com/entelisteam/lbaf-rector)). Обновляется только вручную: поднять constraint в `composer.json` и выполнить `composer update`.
- **Minor (`1.2` → `1.3`)** — новая функциональность, обратная совместимость сохранена.
- **Patch (`1.2.0` → `1.2.1`)** — исправления без изменения публичного API.

Правило: **если изменение требует Rector-миграции — это major**, иначе minor или patch.

Зависимости на пакеты LBAF указываются через caret (`"entelisteam/lbaf-*": "^1.2"`): minor и patch подтягиваются обычным `composer update`, major автоматически не устанавливается. После обновления Rector-миграции применяются автоматически (хук `post-update-cmd`); если хук не настроен — выполните `composer rector:fix`.

License
-------

[](#license)

MIT.

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance95

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~13 days

Total

5

Last Release

22d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5281445?v=4)[Dim Entelis](/maintainers/dentelis)[@dentelis](https://github.com/dentelis)

---

Top Contributors

[![dentelis](https://avatars.githubusercontent.com/u/5281445?v=4)](https://github.com/dentelis "dentelis (17 commits)")

---

Tags

jsonfactorydeserializationhydratordtoattribute

###  Code Quality

TestsPHPUnit

Static AnalysisRector

### Embed Badge

![Health badge](/badges/entelisteam-lbaf-hydrator/health.svg)

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

###  Alternatives

[jms/serializer

Library for (de-)serializing data of any complexity; supports XML, and JSON.

2.3k141.9M937](/packages/jms-serializer)[jms/serializer-bundle

Allows you to easily serialize, and deserialize data of any complexity

1.8k92.4M684](/packages/jms-serializer-bundle)[brick/json-mapper

Maps JSON data to strongly typed PHP DTOs

20665.9k4](/packages/brick-json-mapper)[thunderer/serializard

Flexible serializer

2667.9k1](/packages/thunderer-serializard)

PHPackages © 2026

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