PHPackages                             jurasciix/datamapper - 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. [Database &amp; ORM](/categories/database)
4. /
5. jurasciix/datamapper

ActiveLibrary[Database &amp; ORM](/categories/database)

jurasciix/datamapper
====================

1.1.3(2mo ago)019PHPPHP ^8.1

Since Feb 22Pushed 2mo agoCompare

[ Source](https://github.com/JuraSciix/PhpDataMapper)[ Packagist](https://packagist.org/packages/jurasciix/datamapper)[ RSS](/packages/jurasciix-datamapper/feed)WikiDiscussions master Synced today

READMEChangelog (4)Dependencies (8)Versions (6)Used By (0)

DataMapper
==========

[](#datamapper)

Библиотека для отображения данных на объекты PHP с возможностями валидации.

Внедрение
---------

[](#внедрение)

Быстрый пример:

```
$mapper = new DataMapper();

$ticket = $mapper->deserialize(json_decode($jsonString, true), Ticket::class);
// ...

class Ticket {
    /**
     * @param string $text Текст обращения.
     * @param string[] $tags Темы.
     * @param DateTime $created Дата создания.
     */
    function __construct(
        readonly string $text
        readonly array $tags,
        readonly DateTime $created,
    ) {}
}
```

Пример с опциями:

```
// Все опции снизу соответствуют значениям по умолчанию и перерчислены для наглядности.
$mapper = DataMapper::builder()
    ->caseSensitive(false) // Отключаем чувствительность к регистру
    ->caseStyle(CaseStyle::SNAKE_CASE) // Выбираем snake_case стиль написания для ключей
    ->omitUnmatchedKeys(true) // Игнорируем неизвестные ключи
    ->allowTypeConverting(true) // Разрешаем приводить типы. Напр., int ↔ string
    ->dateTimeFormat(DateTime::ATOM) // Выбираем формат для дат
    ->timeZone(new DateTimeZone('Europe/Moscow')) // Выбираем часовой пояс
    ->build();
// ...
```

Возможности и Roadmap
---------------------

[](#возможности-и-roadmap)

- Поддержка списковых и ассоциативных массивов
- Поддержка phpdoc для уточнения типов
- Поддержка обобщенных типов с произвольным числом параметров
- Переопределение геттеров и сеттеров для свойств
- Поддержка классов **Date/Time** и **SPL**.
- Поддержка классов-перечислений (см. [Классы Перечислений](#%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D1%8B-%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9-enum))
- Интеграция сторонних библиотек

К интеграции планируются следующие библиотеки:

- `moneyphp/money`
- `brick/math`
- `mjaschen/phpgeo`
- `darsyn/ip`
- `nesbot/carbon`
- `ramsey/uuid`
- `psr/clock`
- `ext-ds`

Установка
---------

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

Требования:

- PHP ≥ 8.1
- Composer

Установка с помощью **Composer**:

```
composer require jurasciix/datamapper:^1.0

```

Представления библиотеки
------------------------

[](#представления-библиотеки)

> Библиотека не обрабатывает возможности PHP версии выше 8.1, таким, как [Property Hooks](https://www.php.net/manual/en/language.oop5.property-hooks.php) и [Lazy Objects](https://www.php.net/manual/en/language.oop5.lazy-objects.php).

### Сепарация слоев данных и логики

[](#сепарация-слоев-данных-и-логики)

Библиотека порицает смешивание слоев данных и логики, поэтому стремится работать с *чистыми* объектами, создавая их самостоятельно.

> Как определить свою логику обработки данных, рассказывается в главе [Адаптеры](#%D0%B0%D0%B4%D0%B0%D0%BF%D1%82%D0%B5%D1%80%D1%8B).

Процесс анализа классов опирается на свойства классов. Как следствие, процесс наследует все [особенности рефлексии PHP](#%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D1%80%D0%B5%D1%84%D0%BB%D0%B5%D0%BA%D1%81%D0%B8%D0%B8-php).

### Классы-перечислений (enum)

[](#классы-перечислений-enum)

> В настоящий момент библиотека не поддерживает классы-перечисления, чтобы придерживаться идеологической и архитектурной простоты.

**Проблемы классов-перечислений**. Значения класса-перечисления (значения-перечесления) констатированы в коде, поэтому если в данных встретится новое значение, у нас не останется иного выбора, кроме как выбросить исключение.

Пример:

```
enum State: int {
    case OPEN = 0;
    case CLOSE = 1;
}

$mapper = new DataMapper();
// Гарантированно привело бы к ошибке.
$mapper->map(2, State::class);
```

**Потенциальное решение через слияние**.

> Под **слиянием** понимается взятие специального значения-перечисления того же класса-перечисления в случае, если встретилось неизвестное значение.

**Проблема**: важно отслеживать появление неизвестных значений, поэтому решение через слияние не подходит.

### Адаптеры

[](#адаптеры)

Адаптер это объект, занимающийся сериализацией и десериализацией определенного семейства типов.

> Про семейства типов рассказывается в главе [Связь между типами](#%D1%81%D0%B2%D1%8F%D0%B7%D1%8C-%D0%BC%D0%B5%D0%B6%D0%B4%D1%83-%D1%82%D0%B8%D0%BF%D0%B0%D0%BC%D0%B8)

Если данные имеют неудобный вид, с которым не может работать библиотека, есть возможность определить собственный адаптер:

```
// Добавляем собственный адаптер для типа GeoCoords
$mapper = DataMapper::builder()
    ->registerAdapter(GeoCoords::class, new class implements AdapterInterface {
        function deserialize(DataMapper $mapper, mixed $data) {
            return new GeoCoords($data[0], $data[1]);
        }
        function serialize(DataMapper $mapper, mixed $data) {
            return [$data->lat, $data->lon];
        }
    })
    ->build();

// Приводим неудобные данные к типу GeoCoords.
$coords = $mapper->deserialize([41.53898, -110.78358], GeoCoords::class);
assert($coords instanceof GeoCoords);

class GeoCoords {
    function __construct(
        readonly float $lat,
        readonly float $lon
    ) {}
}
```

### Обобщенные типы

[](#обобщенные-типы)

> Обобщенные типы не поддерживаются на уровне анализа из-за быстрорастущей комплексности этого процесса.

Пример:

```
/**
 * @template T
 */
case TList {
    /** @var T[] */
    public $array;
}

/**
 * @template-extends TList
 */
class IntList extends TList {}
```

Анализатору придётся учесть всю иерархию типов и мн-во разных тегов: `template`, `extends`, `implements`, включая разновидности для `psalm` и т. д.

Более того, возникают нежелательно сложные вопросы с ограничениями параметров.

Тем не менее библиотека умеет распознавать обобщенные типы у свойств. Пример:

```
class Polygon {
    /** @var SplFixedArray */
    public SplFixedArray $points;
}
class Vertex2D {
    public int $x, $y;
}
```

Анализатор полностью учтёт параметр `Vertex2D` в типе и отобразит данные ожидаемым образом.

> В случаях, когда параметры опущены, библиотека автоматически доопределяет их до `mixed`.

### Связь между типами

[](#связь-между-типами)

> Связь между типами учитывается только вручную созданными адаптерами.

> Для адаптеров, которые сгенерированы автоматически библиотекой, все типы инвариантны.

Для дасериализации каждого типа `T` библиотека ищет любой подходящий (контравариантный) десериализатор.

Для сериализации каждого типа `T` библиотека ищет любой подходящий (ковариантный) сериализатор.

Пример:

```
interface NameAware {
    function getName(): string;
}
interface RatingAware {
    function getRating(): float;
}
class NameAndRating implements NameAware, RatingAware {
    function __construct(
        readonly string $name,
        readonly float $rating,
    ) {}

    function getName(): string { return $this->name; }
    function getRating(): float { return $this->rating; }
}

$mapper = DataMapper::builder()
    ->registerAdapter(NameAndRating::class, new class implements AdapterInterface {
        function deserialize(DataMapper $mapper, mixed $data) {
            return new NameAndRating($data['name'], $data['rating']);
        }
        function serialize(DataMapper $mapper, mixed $data) {
            return [
                'name' => $data->getName(),
                'rating' => $data->getRating()
            ];
        }
    })
    ->builder();

// Ошибка: отсутствует ключ `rating`
$nameAware = $map->deserialize(['name' => '...'], NameAware::class);
```

### Особенности рефлексии PHP

[](#особенности-рефлексии-php)

Рассмотрим следующий код:

```
case Base {
    private $foo;
}

class Der extends Base {}
```

При работе с классом `Der`, поле `Base::$foo` не будет учтено анализатором и проигнорируется. Чтобы исправить это, поле `Base::$foo` должно иметь область видимости, как минимум, `protected`. Геттеры и сеттеры не оказывают влияние на поведение анализатора, так как это условное ограничение рефлексии PHP, которое поощряется из принципа простоты.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance87

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

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

Total

5

Last Release

68d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7b9c48a10049ebe3b1fb4f907c36f9c2cbaaafda66d57f19b4e1cef7f0652534?d=identicon)[JuraSciix](/maintainers/JuraSciix)

---

Top Contributors

[![JuraSciix](https://avatars.githubusercontent.com/u/53406677?v=4)](https://github.com/JuraSciix "JuraSciix (78 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/jurasciix-datamapper/health.svg)

```
[![Health](https://phpackages.com/badges/jurasciix-datamapper/health.svg)](https://phpackages.com/packages/jurasciix-datamapper)
```

###  Alternatives

[rector/rector-src

Instant Upgrade and Automated Refactoring of any PHP code

136406.3k14](/packages/rector-rector-src)[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k11.2M101](/packages/dedoc-scramble)[nette/caching

⏱ Nette Caching: library with easy-to-use API and many cache backends.

44119.3M404](/packages/nette-caching)[ssch/typo3-rector

Instant fixes for your TYPO3 PHP code by using Rector.

2603.2M436](/packages/ssch-typo3-rector)[nette/database

💾 Nette Database: layer with a familiar PDO-like API but much more powerful. Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.

5687.0M262](/packages/nette-database)[ublaboo/datagrid

DataGrid for Nette Framework: filtering, sorting, pagination, tree view, table view, translator, etc

3042.0M26](/packages/ublaboo-datagrid)

PHPackages © 2026

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