PHPackages                             perfilov/php-dto-packer - 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. perfilov/php-dto-packer

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

perfilov/php-dto-packer
=======================

Blazing-fast PHP library to convert arrays, JSON &amp; objects into strongly typed DTOs (and back)

6.0.5(8mo ago)32.5k↓18.5%MITPHPPHP &gt;=8.1CI passing

Since Mar 2Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/PerfilovStanislav/php-dto-packer)[ Packagist](https://packagist.org/packages/perfilov/php-dto-packer)[ Docs](https://beacons.ai/stanislavperfilov)[ RSS](/packages/perfilov-php-dto-packer/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (14)Used By (0)

**DtoPacker** is a small PHP library to pack data into a strongly-typed value object structure. Use it when you want to transfer objects between services and send to front.

[![CI](https://github.com/PerfilovStanislav/php-dto-packer/actions/workflows/tests.yml/badge.svg)](https://github.com/PerfilovStanislav/php-dto-packer/actions/workflows/tests.yml)[![Packagist](https://camo.githubusercontent.com/3ba981b8ba5230a6e6be3315c96cdcaf3b2f06ca2375ad7e286fc824b2e16e2e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f70657266696c6f762f7068702d64746f2d7061636b65722e737667)](https://packagist.org/packages/perfilov/php-dto-packer)[![Downloads](https://camo.githubusercontent.com/301e5e5366ae739cc8fa72ce55e05f393b9d2e0d13d41ac14044bc3782a53e5b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f70657266696c6f762f7068702d64746f2d7061636b65722e737667)](https://packagist.org/packages/perfilov/php-dto-packer)[![Codecov](https://camo.githubusercontent.com/b3cc008c2737b2ca734da2c00298a0551f5aad12027bb1d8be6834bd6b068d79/68747470733a2f2f636f6465636f762e696f2f67682f50657266696c6f765374616e69736c61762f7068702d64746f2d7061636b65722f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/PerfilovStanislav/php-dto-packer)[![PHP](https://camo.githubusercontent.com/9aff46474eba2027d0b286e96d92707d55aae170e25cfc8f986e9c3f556b5667/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f70657266696c6f762f7068702d64746f2d7061636b65722e737667)](https://www.php.net/)[![License](https://camo.githubusercontent.com/91cfe2f83aee13f702ee98a42ce8666753ee1d77558c66d7e9850a16193d8923/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f50657266696c6f765374616e69736c61762f7068702d64746f2d7061636b65722e737667)](https://github.com/PerfilovStanislav/php-dto-packer/blob/main/LICENSE)

#### *Write to me if you need additional features* [![contact](./source/telegram.svg "telegram @PerfilovStanislav") PerfilovStanislav](https://PerfilovStanislav.t.me)

[](#write-to-me-if-you-need-additional-features--perfilovstanislav)

---

Install
=======

[](#install)

```
composer require perfilov/php-dto-packer
```

---

- [Example](#quick-example)
- [Aliases](#aliases)
- [Typed arrays](#typed-arrays)
- [Mutators](#mutators)
- [Validators](#validators)
- [Dimension](#dimension)

Quick Example
=============

[](#quick-example)

```
use DtoPacker\AbstractDto;

class PurchaseDto extends AbstractDto
{
    public int $id;
    protected \DateTimeInterface $date;
    protected ProductDto $product;
}

class ProductDto extends AbstractDto
{
    public string $name;
    public float $price;
}

$data = [
    'id'      => 100,
    'date'    => '2025-10-16',
    'product' => [
        'name'  => 'apple',
        'price' => 10.5,
    ]
];

$purchase = new PurchaseDto($data);

echo "$purchase";
dd($purchase)
```

### Output:

[](#output)

```
{"id":100,"date":"2025-10-16T00:00:00.000+00:00","product":{"name":"apple","price":10.5}}
```

```
PurchaseDto {
    +id: 100
    #date: DateTimeImmutable @1760572800 {
        date: 2025-10-16 00:00:00.0 +00:00
    }
    #product: ProductDto {
        +name: "apple"
        +price: 10.5
    }
}
```

---

Aliases
=======

[](#aliases)

```
use DtoPacker\AbstractDto;
use DtoPacker\Alias;

class UserDto extends AbstractDto
{
    #[Alias('lastname', 'family_name')]
    protected string $surname;
}

$data = [
    'lastname' => 'Mask',
];

$user = new UserDto($data);

echo $user->surname; // output: Mask

$user->family_name = 'Trump'; // output: Trump
```

---

Typed arrays
============

[](#typed-arrays)

```
use DtoPacker\AbstractDto;
use DtoPacker\Dimension;

class ExampleDto extends AbstractDto
{
    protected array|string $strings;
    protected array|int $ints;
    protected array|float $floats;
    protected array|bool $bools;
    protected array|\DateTimeInterface $dates;
    protected array|Object $objects;
    protected array|UserDto $users;

    #[Dimension(2)]
    protected array|int $multiInts;
}

class UserDto extends AbstractDto
{
    public string $name;
}

$datetime = new \DateTime('2030-01-01');

$object = new \stdClass();
$object->x = 2;

$user = new UserDto(['name' => 'Trump']);

$data = [
    'strings'   => ['Mask', 'Trump'],
    'ints'      => [100, 200, 300],
    'floats'    => [10.5, 99.9],
    'bools'     => [true, false],
    'dates'     => ['2025-10-16', $datetime],
    'objects'   => [['x' => 1], $object],
    'users'     => [['name' => 'Elon'], $user],
    'multiInts' => [[100, 200], [300, 400, 500]],
];

$dto = new ExampleDto($data);
echo $dto;
```

### Output:

[](#output-1)

```
{
  "strings": ["Mask", "Trump"],
  "ints": [100, 200, 300],
  "floats": [10.5, 99.9],
  "bools": [true, false],
  "dates": ["2025-10-16T00:00:00.000+00:00", "2030-01-01T00:00:00.000+00:00"],
  "objects": [
    {"x": 1},
    {"x": 2}
  ],
  "users": [
    {"name": "Elon"},
    {"name": "Trump"}
  ],
  "multiInts":[
    [100,200],
    [300,400,500]
  ]
}
```

---

Mutators
========

[](#mutators)

```
use DtoPacker\AbstractDto;
use DtoPacker\PreMutator;

class UserDto extends AbstractDto
{
    #[PreMutator('ucfirst', [CustomMutator::class, 'addPrefixMr'])]
    protected string $lastname;
}

class CustomMutator
{
    public static function addPrefixMr(string $value): string
    {
        return "Mr $value";
    }
}

$user = new UserDto([
    'lastname' => 'elon'
]);

echo $user->lastname; // output: "Mr Elon"
```

---

Validators
==========

[](#validators)

### FieldValidators - example

[](#fieldvalidators---example)

> **FieldValidators** - validate field's value

```
use DtoPacker\AbstractDto;
use DtoPacker\Validators\Array;
use DtoPacker\Validators\Bool;
use DtoPacker\Validators\Datetime;
use DtoPacker\Validators\FieldValidators;
use DtoPacker\Validators\Numeric;
use DtoPacker\Validators\String;
use DtoPacker\Validators\Mixed;

class ExampleDto extends AbstractDto
{
    #[FieldValidators(
        new Numeric\Min(10),
        new Numeric\Max(20),
        new Numeric\Between(1, 100),
    )]
    protected int $int;

    #[FieldValidators(
        new String\Alpha(),
        new String\Card(),
        new String\Cuid(),
        new String\Email(),
        new String\Email(),
        new String\Ip(),
        new String\IpV4(),
        new String\IpV6(),
        new String\Json(),
        new String\LengthMin(10),
        new String\LengthMax(20),
        new String\LengthBetween(1, 100),
        new String\MacAddress(),
        new String\NanoId(),
        new String\Regex('/^\d$/'),
        new String\Ulid(),
        new String\Url(),
        new String\Uuid\Uuid(),
    )]
    protected string $string;

    #[FieldValidators(
        new Bool\IsFalse(),
        new Bool\IsTrue(),
    )]
    protected bool $bool;

    #[FieldValidators(
        new Datetime\After('2000-01-01'),
        new Datetime\Before('2025-12-31'),
        new Datetime\Between('2000-01-01', '2026-01-01'),
    )]
    protected \DateTimeInterface $datetime;

    #[FieldValidators(
        new Mixed\In([100, 'paid', true]),
        new Mixed\Required(),
        new Mixed\Requires(['string', 'bool']),
    )]
    protected string $mixed;

    #[FieldValidators(
        new Array\CountBetween(1, 100),
        new Array\CountMin(1),
        new Array\CountMax(10),
        new Array\Unique(),
        new Array\UniqueIntegers(),
    )]
    protected array|int $ints;

    #[FieldValidators(
        new Array\UniqueStrings(),
    )]
    protected array|string $strings;
}

$data = [
    'int'      => 5,
    'string'   => 'Mask', 'Trump',
    'bool'     => true,
    'datetime' => '2020-06-15',
    'mixed'    => 'paid',
    'ints'     => [2, 5],
    'strings'  => ['Elon', 'Trump'],
];

try {
    $dto = new ExampleDto($data);
} catch (ValidationExceptions $e) {
    print_r($e->toArray());
}
```

### Output:

[](#output-2)

```
Array
(
    [0] => Array
        (
            [field] => int
            [error] => Int must be at least 10
            [path]  => int
        )

    [1] => Array
        (
            [field] => string
            [error] => String must be a valid card number
            [path]  => string
        )
    ...
)
```

---

### ArrayValidators - example

[](#arrayvalidators---example)

> **ArrayValidators** - validate each item of array

```
use DtoPacker\AbstractDto;
use DtoPacker\Validators\ArrayValidators;
use DtoPacker\Validators\Numeric\Max;
use DtoPacker\Validators\Numeric\Min;

class ExampleDto extends AbstractDto
{
    #[ArrayValidators(
        new Min(10),
        new Max(20),
    )]
    protected array|int $ints;
}

$data = [
    'ints' => [5, 15, 25],
];

try {
    $dto = new ExampleDto($data);
} catch (ValidationExceptions $e) {
    print_r($e->toArray());
}
```

### Output:

[](#output-3)

```
Array
(
    [0] => Array
        (
            [field] => ints
            [error] => [0] ints must be at least 10
            [path]  => ints[0]
            [index] => Array
                (
                    [0] => 0
                )

        )
    [1] => Array
        (
            [field] => ints
            [error] => [2] ints may not be greater than 20
            [path]  => ints[2]
            [index] => Array
                (
                    [0] => 2
                )

        )
)
```

---

### Chain of validators - example

[](#chain-of-validators---example)

```
use DtoPacker\AbstractDto;
use DtoPacker\Validators\FieldValidators;
use DtoPacker\Validators\Numeric\Max;

class ExampleDto extends AbstractDto
{
    #[FieldValidators(
        [
            new Max(10),
            new Max(20), // will be skipped if one of the previous validators returns an error
        ],
        new Max(30)
    )]
    protected int $int;
}

$data = [
    'ints' => [5, 15, 25],
];

try {
    $dto = new ExampleDto($data);
} catch (ValidationExceptions $e) {
    print_r($e->toArray());
}
```

### Output:

[](#output-4)

```
Array
(
    [0] => Array
        (
            [field] => int
            [error] => Int may not be greater than 10
            [path]  => int
        )

    [1] => Array
        (
            [field] => int
            [error] => Int may not be greater than 30
            [path]  => ints
        )

)
```

---

Dimension
=========

[](#dimension)

```
use DtoPacker\AbstractDto;
use DtoPacker\Dimension;

class ExampleDto extends AbstractDto
{
    #[Dimension(2)]
    protected array|int $ints;
}

$data = [
    'ints' => [[5, 15, 25], [100, 200]],
];

$dto = new ExampleDto($data);
print_r($dto->toArray());
```

### Output:

[](#output-5)

```
Array
(
    [ints] => Array
        (
            [0] => Array
                (
                    [0] => 5
                    [1] => 15
                    [2] => 25
                )

            [1] => Array
                (
                    [0] => 100
                    [1] => 200
                )

        )

)
```

---

### Benchmark

[](#benchmark)

Check out the [benchmark](https://github.com/PerfilovStanislav/php-dto-benchmark) comparison of popular libraries

[![image](https://raw.githubusercontent.com/PerfilovStanislav/php-dto-benchmark/main/dto-benchmark.gif)](https://raw.githubusercontent.com/PerfilovStanislav/php-dto-benchmark/main/dto-benchmark.gif)

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance80

Actively maintained with recent releases

Popularity23

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity61

Established project with proven stability

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

Recently: every ~0 days

Total

13

Last Release

240d ago

Major Versions

3.0.0 → 4.0.02023-03-02

4.0.3 → 5.0.02023-03-02

5.3.0 → 6.0.02025-09-11

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/18257506?v=4)[PerfilovStanislav](/maintainers/PerfilovStanislav)[@PerfilovStanislav](https://github.com/PerfilovStanislav)

---

Top Contributors

[![PerfilovStanislav](https://avatars.githubusercontent.com/u/18257506?v=4)](https://github.com/PerfilovStanislav "PerfilovStanislav (27 commits)")

---

Tags

phpjsonarrayperformanceValue Objectserializerconversionencodedecodetreemappingmapperhydratordata-transfer-objectfastlightweightdtoobject mapperstrongly-typedtype-safeobject conversiondeserializerpacker

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/perfilov-php-dto-packer/health.svg)

```
[![Health](https://phpackages.com/badges/perfilov-php-dto-packer/health.svg)](https://phpackages.com/packages/perfilov-php-dto-packer)
```

###  Alternatives

[cuyz/valinor

Dependency free PHP library that helps to map any input into a strongly-typed structure.

1.5k9.2M108](/packages/cuyz-valinor)[zakirullin/mess

Convenient array-related routine &amp; better type casting

21228.9k2](/packages/zakirullin-mess)[event4u/data-helpers

Framework-agnostic PHP library for data mapping, DTOs and utilities. Includes DataMapper, SimpleDto/LiteDto, DataAccessor/Mutator/Filter and helper classes (MathHelper, EnvHelper, etc.). Works with Laravel, Symfony/Doctrine or standalone PHP.

1421.5k](/packages/event4u-data-helpers)[orisai/object-mapper

Raw data mapping to validated objects

1133.5k2](/packages/orisai-object-mapper)

PHPackages © 2026

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