PHPackages                             ddd-mapper-generator/ddd-mapper-generator - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. ddd-mapper-generator/ddd-mapper-generator

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

ddd-mapper-generator/ddd-mapper-generator
=========================================

v1.0.8(6mo ago)09MITPHPPHP ^8.1

Since Sep 23Pushed 6mo agoCompare

[ Source](https://github.com/MegaEvil/ddd-mapper-generator)[ Packagist](https://packagist.org/packages/ddd-mapper-generator/ddd-mapper-generator)[ RSS](/packages/ddd-mapper-generator-ddd-mapper-generator/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (4)Versions (9)Used By (0)

🧩 DDD Mapper Generator для PHP
==============================

[](#-ddd-mapper-generator-для-php)

> 🚀 **Автоматическая генерация высокопроизводительных, типизированных мапперов между Domain Entity и DTO в стиле DDD.**
> Поддержка конструкторов, коллекций, вложенных объектов, кастомных маппингов и DI-совместимости.

Этот инструмент генерирует **чистые PHP-классы мапперов** на этапе сборки — без Reflection в рантайме.
Подходит для проектов с архитектурой: **DDD, Clean Architecture, Hexagonal, CQRS**.

---

📌 Оглавление
------------

[](#-оглавление)

- [🚀 Быстрый старт](#-%D0%B1%D1%8B%D1%81%D1%82%D1%80%D1%8B%D0%B9-%D1%81%D1%82%D0%B0%D1%80%D1%82)
- [🔧 Требования](#-%D1%82%D1%80%D0%B5%D0%B1%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
- [🧩 Примеры использования](#-%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
    - [1. Простой маппинг свойств](#1-%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B9-%D0%BC%D0%B0%D0%BF%D0%BF%D0%B8%D0%BD%D0%B3-%D1%81%D0%B2%D0%BE%D0%B9%D1%81%D1%82%D0%B2)
    - [2. Маппинг через конструкторы](#2-%D0%BC%D0%B0%D0%BF%D0%BF%D0%B8%D0%BD%D0%B3-%D1%87%D0%B5%D1%80%D0%B5%D0%B7-%D0%BA%D0%BE%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D0%BE%D1%80%D1%8B)
    - [3. Коллекции (массивы объектов)](#3-%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8-%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2%D1%8B-%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BE%D0%B2)
    - [4. Вложенные объекты](#4-%D0%B2%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B)
    - [5. Кастомные имена полей (`MapTo`)](#5-%D0%BA%D0%B0%D1%81%D1%82%D0%BE%D0%BC%D0%BD%D1%8B%D0%B5-%D0%B8%D0%BC%D0%B5%D0%BD%D0%B0-%D0%BF%D0%BE%D0%BB%D0%B5%D0%B9-maptop)
    - [6. Кастомные методы маппинга](#6-%D0%BA%D0%B0%D1%81%D1%82%D0%BE%D0%BC%D0%BD%D1%8B%D0%B5-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D1%8B-%D0%BC%D0%B0%D0%BF%D0%BF%D0%B8%D0%BD%D0%B3%D0%B0)
    - [7. Несколько DTO для одной Entity](#7-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-dto-%D0%B4%D0%BB%D1%8F-%D0%BE%D0%B4%D0%BD%D0%BE%D0%B9-entity)
- [⚙️ Конфигурация](#%EF%B8%8F-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F)
    - [Автоматическое сопоставление](#%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%81%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5)
    - [Явная конфигурация (`mappers.yaml`)](#%D1%8F%D0%B2%D0%BD%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F-mappersyaml)
    - [Атрибуты на DTO (`MapsFromEntity`)](#%D0%B0%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D1%8B-%D0%BD%D0%B0-dto-mapsfromentity)
- [🖥️ CLI Команды](#%EF%B8%8F-cli-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B)
- [🧰 Makefile команды](#%EF%B8%8F-makefile-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B)
- [💡 Советы и лучшие практики](#-%D1%81%D0%BE%D0%B2%D0%B5%D1%82%D1%8B-%D0%B8-%D0%BB%D1%83%D1%87%D1%88%D0%B8%D0%B5-%D0%BF%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%BA%D0%B8)
- [🤝 Вклад в проект](#-%D0%B2%D0%BA%D0%BB%D0%B0%D0%B4-%D0%B2-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82)

---

🚀 Быстрый старт
---------------

[](#-быстрый-старт)

### 1. Установка

[](#1-установка)

```
composer install
```

### 2. Создай Entity и DTO

[](#2-создай-entity-и-dto)

```
// src/Entity/User.php
class User
{
    private int $id;
    private string $firstName;
    private string $lastName;

    public function __construct(int $id, string $firstName, string $lastName)
    {
        $this->id = $id;
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function getId(): int { return $this->id; }
    public function getFirstName(): string { return $this->firstName; }
    public function getLastName(): string { return $this->lastName; }
}
```

```
// src/Dto/UserProfileDto.php
class UserProfileDto
{
    public function __construct(
        public int $id,
        public string $fullName
    ) {}
}
```

### 3. Запусти генерацию

[](#3-запусти-генерацию)

```
php bin/console generate:mappers
```

### 4. Используй маппер

[](#4-используй-маппер)

```
// generated/Mapper/UserToProfileMapper.php (автоматически сгенерирован)
class UserToProfileMapper
{
    public function toDto(User $entity): UserProfileDto
    {
        return new UserProfileDto(
            id: $entity->getId(),
            fullName: $entity->getFirstName() . ' ' . $entity->getLastName()
        );
    }
}
```

> ⚠️ Но стоп! Мы не указали, как маппить `fullName` — давай это исправим 👇

---

🧩 Примеры использования
-----------------------

[](#-примеры-использования)

---

### 1. Простой маппинг свойств

[](#1-простой-маппинг-свойств)

Если имена совпадают — ничего дополнительно указывать не нужно.

```
// src/Entity/Address.php
class Address
{
    public function __construct(
        public string $street,
        public string $city
    ) {}
}
```

```
// src/Dto/AddressDto.php
class AddressDto
{
    public string $street;
    public string $city;
}
```

✅ Результат:

```
class AddressMapper
{
    public function toDto(Address $entity): AddressDto
    {
        $dto = new AddressDto();
        $dto->street = $entity->street;
        $dto->city = $entity->city;
        return $dto;
    }
}
```

---

### 2. Маппинг через конструкторы

[](#2-маппинг-через-конструкторы)

Если DTO или Entity используют конструкторы — маппер использует их.

```
// src/Dto/UserReadDto.php
class UserReadDto
{
    public function __construct(
        public int $userId,
        public string $name
    ) {}
}
```

```
// src/Entity/User.php (тот же, что выше)
```

✅ Результат:

```
class UserReadMapper
{
    public function toDto(User $entity): UserReadDto
    {
        return new UserReadDto(
            userId: $entity->getId(),
            name: $entity->getFirstName() . ' ' . $entity->getLastName()
        );
    }
}
```

> Но `name` не совпадает с геттерами — нужно указать маппинг вручную → см. пример 5.

---

### 3. Коллекции (массивы объектов)

[](#3-коллекции-массивы-объектов)

Используй атрибут `#[MapCollection]`.

```
// src/Entity/User.php
use App\Attribute\MapCollection;

class User
{
    #[MapCollection(Address::class)]
    private array $addresses;

    public function __construct(int $id, string $firstName, string $lastName, array $addresses = [])
    {
        $this->id = $id;
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->addresses = $addresses;
    }

    public function getAddresses(): array { return $this->addresses; }
}
```

```
// src/Dto/UserReadDto.php
use App\Attribute\MapCollection;

class UserReadDto
{
    public function __construct(
        public int $userId,
        public string $name,
        #[MapCollection(AddressDto::class)]
        public array $addresses
    ) {}
}
```

✅ Результат:

```
class UserReadMapper
{
    public function __construct(private AddressMapper $addressMapper) {}

    public function toDto(User $entity): UserReadDto
    {
        return new UserReadDto(
            userId: $entity->getId(),
            name: $entity->getFirstName() . ' ' . $entity->getLastName(),
            addresses: array_map(
                fn(Address $item) => $this->addressMapper->toDto($item),
                $entity->getAddresses()
            )
        );
    }
}
```

---

### 4. Вложенные объекты

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

Просто используй тип в конструкторе или свойстве — маппер сам определит зависимость.

```
// src/Entity/Order.php
class Order
{
    public function __construct(
        public int $id,
        public User $user
    ) {}
}
```

```
// src/Dto/OrderDto.php
class OrderDto
{
    public function __construct(
        public int $id,
        public UserReadDto $user
    ) {}
}
```

✅ Результат:

```
class OrderMapper
{
    public function __construct(private UserReadMapper $userReadMapper) {}

    public function toDto(Order $entity): OrderDto
    {
        return new OrderDto(
            id: $entity->id,
            user: $this->userReadMapper->toDto($entity->user)
        );
    }
}
```

---

### 5. Кастомные имена полей (`MapTo`)

[](#5-кастомные-имена-полей-mapto)

Когда имена в Entity и DTO не совпадают.

```
// src/Entity/User.php
use App\Attribute\MapTo;

class User
{
    #[MapTo('userId')]
    private int $id;

    #[MapTo('fullName')]
    private string $firstName;

    private string $lastName;

    public function __construct(int $id, string $firstName, string $lastName)
    {
        $this->id = $id;
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function getId(): int { return $this->id; }
    public function getFirstName(): string { return $this->firstName; }
    public function getLastName(): string { return $this->lastName; }
}
```

```
// src/Dto/UserProfileDto.php
class UserProfileDto
{
    public int $userId;
    public string $fullName;
}
```

✅ Результат:

```
class UserToProfileMapper
{
    public function toDto(User $entity): UserProfileDto
    {
        $dto = new UserProfileDto();
        $dto->userId = $entity->getId();
        $dto->fullName = $entity->getFirstName(); // ← НЕПРАВИЛЬНО — не хватает lastName!
        return $dto;
    }
}
```

> ⚠️ Так не пойдёт — нужно кастомное преобразование → см. пример 6.

---

### 6. Кастомные методы маппинга

[](#6-кастомные-методы-маппинга)

Добавь статический метод в DTO и укажи его в `MapTo`.

```
// src/Dto/UserProfileDto.php
class UserProfileDto
{
    public int $userId;
    public string $fullName;

    public static function buildFullName(string $firstName, string $lastName): string
    {
        return "$firstName $lastName";
    }
}
```

```
// src/Entity/User.php
use App\Attribute\MapTo;

class User
{
    #[MapTo('userId')]
    private int $id;

    #[MapTo('fullName', mapperMethod: 'UserProfileDto::buildFullName')]
    private string $firstName;

    private string $lastName;

    public function __construct(int $id, string $firstName, string $lastName)
    {
        $this->id = $id;
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function getId(): int { return $this->id; }
    public function getFirstName(): string { return $this->firstName; }
    public function getLastName(): string { return $this->lastName; }
}
```

✅ Результат:

```
class UserToProfileMapper
{
    public function toDto(User $entity): UserProfileDto
    {
        $dto = new UserProfileDto();
        $dto->userId = $entity->getId();
        $dto->fullName = UserProfileDto::buildFullName(
            $entity->getFirstName(),
            $entity->getLastName()
        );
        return $dto;
    }
}
```

---

### 7. Несколько DTO для одной Entity

[](#7-несколько-dto-для-одной-entity)

#### Вариант A: Автоматически (по именам)

[](#вариант-a-автоматически-по-именам)

```
// src/Dto/UserReadDto.php
class UserReadDto
{
    public int $id;
    public string $name;
}
```

```
// src/Dto/UserProfileDto.php
class UserProfileDto
{
    public int $id;
    public string $displayName;
}
```

```
// src/Dto/UserShortDto.php
class UserShortDto
{
    public int $id;
}
```

→ Генерируются:

- `UserToReadMapper.php`
- `UserToProfileMapper.php`
- `UserToShortMapper.php`

#### Вариант B: Через конфиг `config/mappers.yaml`

[](#вариант-b-через-конфиг-configmappersyaml)

```
mappers:
    - entity: App\Entity\User
      dto: App\Dto\UserReadDto
      mapper_name: UserReadMapper

    - entity: App\Entity\User
      dto: App\Dto\UserProfileDto
      mapper_name: UserProfileMapper
```

#### Вариант C: Через атрибут на DTO

[](#вариант-c-через-атрибут-на-dto)

```
// src/Dto/UserAdminDto.php
use App\Attribute\MapsFromEntity;

#[MapsFromEntity(entityClass: \App\Entity\User::class, mapperName: 'UserAdminMapper')]
class UserAdminDto
{
    public int $id;
    public string $email;
    public bool $isAdmin;
}
```

---

⚙️ Конфигурация
---------------

[](#️-конфигурация)

### Автоматическое сопоставление

[](#автоматическое-сопоставление)

- Ищет все `*.php` в `src/Entity/`.
- Для каждого `User.php` ищет `User*Dto.php` в `src/Dto/`.
- Генерирует `UserToXxxMapper.php`.

### Явная конфигурация (`config/mappers.yaml`)

[](#явная-конфигурация-configmappersyaml)

```
mappers:
    - entity: App\Entity\Order
      dto: App\Dto\OrderSummaryDto
      mapper_name: OrderSummaryMapper

    - entity: App\Entity\Product
      dto: App\Dto\ProductCardDto
      # mapper_name не указан — будет ProductToCardMapper
```

### Атрибуты на DTO (`MapsFromEntity`)

[](#атрибуты-на-dto-mapsfromentity)

```
// src/Dto/ApiUserDto.php
use App\Attribute\MapsFromEntity;

#[MapsFromEntity(\App\Entity\User::class)]
class ApiUserDto
{
    public int $id;
    public string $login;
}
```

```
// src/Dto/UserExportDto.php
use App\Attribute\MapsFromEntity;

#[MapsFromEntity(\App\Entity\User::class, 'UserExportMapper')]
class UserExportDto
{
    public string $exportId;
    public string $fullName;
}
```

---

🖥️ CLI Команды
--------------

[](#️-cli-команды)

```
# Основная генерация
php bin/console generate:mappers

# С опциями
php bin/console generate:mappers \
    --entity-path=src/Domain/Model \
    --dto-path=src/Application/DataTransfer \
    --output-path=src/Infrastructure/Mapper \
    --namespace=App\Infrastructure\Mapper \
    --config=config/custom_mappers.yaml \
    --clear

# Помощь
php bin/console generate:mappers --help
```

---

🧰 Makefile команды
------------------

[](#-makefile-команды)

```
# Установка зависимостей
make install

# Генерация мапперов с очисткой директории
make mappers

# Очистка сгенерированных мапперов
make clean
```

Содержимое `Makefile`:

```
.PHONY: mappers clean install

mappers:
	php bin/console generate:mappers --clear

clean:
	rm -rf generated/Mapper/*

install:
	composer install
```

---

💡 Советы и лучшие практики
--------------------------

[](#-советы-и-лучшие-практики)

- ✅ **Не используй мапперы в домене** — только на границах (Application/Infrastructure).
- ✅ **Делай DTO immutable** — используй конструкторы.
- ✅ **Не коммить `generated/` в репозиторий** — генерируй в CI/CD или pre-commit хуке.
- ✅ **Покрывай тестами кастомные маппинги** — особенно с `mapperMethod`.
- ✅ **Используй осмысленные имена мапперов**: `UserToApiMapper`, `OrderToPdfDtoMapper`.
- ✅ **Добавляй типы и PHPDoc** — это улучшает поддержку в IDE и статических анализаторах.

---

🤝 Вклад в проект
----------------

[](#-вклад-в-проект)

PR приветствуются! Особенно:

- Поддержка Value Objects
- Генерация PHPUnit-тестов для мапперов
- Laravel Artisan-версия команды
- Watch-режим (перегенерация при изменении файлов)
- Интеграция с PHPStan / Psalm
- Docker-образ для изолированного запуска

---

> 🧑‍💻 Сгенерировано с ❤️ для DDD-проектов на PHP
> 🏷️ Версия: 1.0
> 📄 Лицензия: MIT

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance70

Regular maintenance activity

Popularity4

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

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 ~3 days

Total

8

Last Release

201d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d9442d910787a73994d9a591fbe7b3d989f9b02623aa146de0c87aca2d2d1df5?d=identicon)[MegaEvil](/maintainers/MegaEvil)

### Embed Badge

![Health badge](/badges/ddd-mapper-generator-ddd-mapper-generator/health.svg)

```
[![Health](https://phpackages.com/badges/ddd-mapper-generator-ddd-mapper-generator/health.svg)](https://phpackages.com/packages/ddd-mapper-generator-ddd-mapper-generator)
```

###  Alternatives

[symfony/maker-bundle

Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.

3.4k111.1M564](/packages/symfony-maker-bundle)[silverstripe/framework

The SilverStripe framework

7213.5M2.5k](/packages/silverstripe-framework)[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)[symplify/monorepo-builder

Not only Composer tools to build a Monorepo.

5205.3M81](/packages/symplify-monorepo-builder)[roave/backward-compatibility-check

Tool to compare two revisions of a public API to check for BC breaks

5953.3M55](/packages/roave-backward-compatibility-check)[friendsoftypo3/content-blocks

TYPO3 CMS Content Blocks - Content Types API | Define reusable components via YAML

96374.6k23](/packages/friendsoftypo3-content-blocks)

PHPackages © 2026

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