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

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

rjds/php-dto
============

A PHP library to map associative arrays to typed DTOs using attributes.

v1.2.0(2mo ago)0137[3 PRs](https://github.com/RubenJ01/php-dto/pulls)MITPHPPHP ^8.1CI failing

Since Mar 15Pushed 3w agoCompare

[ Source](https://github.com/RubenJ01/php-dto)[ Packagist](https://packagist.org/packages/rjds/php-dto)[ RSS](/packages/rjds-php-dto/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (3)Dependencies (12)Versions (17)Used By (0)

PHP DTO
=======

[](#php-dto)

[![Version](https://camo.githubusercontent.com/71f0b2e6c5dcdbaa436a37a9908342619766bf8bec56130dd63c26e0d4670ffe/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f527562656e4a30312f7068702d64746f3f6c6162656c3d76657273696f6e)](https://camo.githubusercontent.com/71f0b2e6c5dcdbaa436a37a9908342619766bf8bec56130dd63c26e0d4670ffe/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f527562656e4a30312f7068702d64746f3f6c6162656c3d76657273696f6e)[![Packagist Downloads](https://camo.githubusercontent.com/b0513292657324b16988703ed9d54c1514b0c522e77294ba28cc61959b0abaaf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726a64732f7068702d64746f)](https://packagist.org/packages/rjds/php-dto)[![codecov](https://camo.githubusercontent.com/c9c50b0ba53aec44e8965abf9e2fd02c4c9c43d85fa89ad915f6b87dd276708a/68747470733a2f2f636f6465636f762e696f2f6769746875622f527562656e4a30312f7068702d64746f2f67726170682f62616467652e737667)](https://codecov.io/github/RubenJ01/php-dto)[![License](https://camo.githubusercontent.com/ca6ae8f7da2d0dfe96d62b5fd21d41f8d0ea26931dc6b1f441ebb9755d9277a9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f527562656e4a30312f7068702d64746f)](https://camo.githubusercontent.com/ca6ae8f7da2d0dfe96d62b5fd21d41f8d0ea26931dc6b1f441ebb9755d9277a9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f527562656e4a30312f7068702d64746f)

A PHP library to map associative arrays to typed DTOs using attributes.

Installation
------------

[](#installation)

Install from Packagist:

```
composer require rjds/php-dto
```

Requirements:

- PHP 8.1 or higher

Overview
--------

[](#overview)

`DtoMapper` converts associative arrays to typed constructor-based DTOs.

```
use Rjds\PhpDto\Attribute\ArrayOf;
use Rjds\PhpDto\Attribute\CastTo;
use Rjds\PhpDto\Attribute\MapFrom;
use Rjds\PhpDto\DtoMapper;

final class TagDto
{
    public function __construct(
        public readonly string $name,
        public readonly string $url,
    ) {
    }
}

final class ArtistDto
{
    /** @param list $tags */
    public function __construct(
        public readonly string $name,
        #[MapFrom('stats.play_count')]
        #[CastTo('int')]
        public readonly int $playCount,
        #[ArrayOf(TagDto::class)]
        public readonly array $tags,
    ) {
    }
}

$mapper = new DtoMapper();

$artist = $mapper->map([
    'name' => 'Arctic Monkeys',
    'stats' => ['play_count' => '150316'],
    'tags' => [
        ['name' => 'rock', 'url' => 'https://www.last.fm/tag/rock'],
        ['name' => 'indie', 'url' => 'https://www.last.fm/tag/indie'],
    ],
], ArtistDto::class);

echo $artist->playCount;   // 150316 (int)
echo $artist->tags[0]->name; // rock
```

Features
--------

[](#features)

- Zero-boilerplate name-based mapping for constructor arguments
- `#[MapFrom]` support for renamed and nested keys using dot notation
- `#[CastTo]` support for `int`, `float`, `string`, `bool`, and `datetime`
- `#[ArrayOf]` support for mapping nested DTO collections
- Constructor default values respected when source keys are missing
- `MappingException` with structured context (DTO class, parameter, map key, array index, nested `ArrayOf` parent) for easier debugging
- Optional PHPStan extension to narrow `DtoMapper::map()` return types

Errors
------

[](#errors)

Mapping failures throw `Rjds\PhpDto\Exception\MappingException` (a subclass of `InvalidArgumentException`). Use `getDtoClass()`, `getParameterName()`, `getMapKey()`, `getArrayIndex()`, and `getParentDtoClass()` to locate problems in large payloads. Failures while mapping an `#[ArrayOf]` element chain the inner exception via `getPrevious()` / `getPreviousMappingException()`.

Static analysis (PHPStan)
-------------------------

[](#static-analysis-phpstan)

`DtoMapper::map()` is documented with `@template` and `@param class-string` so PHPStan can infer the concrete DTO when you pass a class constant:

```
$artist = $mapper->map($data, ArtistDto::class);
// $artist is inferred as ArtistDto when the second argument is a literal ::class
```

For clearer results in all setups, include the bundled extension from your `phpstan.neon`:

```
includes:
    - vendor/rjds/php-dto/phpstan-extension.neon
```

That extension refines the return type when the second argument is a constant string or a `class-string` type.

Documentation
-------------

[](#documentation)

Extended usage and attribute details are in the [GitHub Wiki](https://github.com/RubenJ01/php-dto/wiki). The wiki is tracked as a Git submodule at [`wiki/`](wiki/). Clone the library with `git clone --recurse-submodules`, or run `git submodule update --init` after a plain clone. To publish wiki edits, commit inside `wiki/` and run `git push origin master` from that directory (GitHub creates the wiki Git remote when you add the first wiki page in the repository **Wiki** tab, if it is not there yet).

Quick Reference
---------------

[](#quick-reference)

### `#[MapFrom]`

[](#mapfrom)

Map a parameter from a different key, including nested paths:

```
#[MapFrom('profile.first_name')]
public readonly string $firstName
```

### `#[CastTo]`

[](#castto)

Cast scalar string input into strongly typed DTO fields:

```
#[CastTo('datetime')]
public readonly \DateTimeImmutable $registeredAt
```

### `#[ArrayOf]`

[](#arrayof)

Map list entries to nested DTO instances:

```
#[ArrayOf(TagDto::class)]
public readonly array $tags
```

Development
-----------

[](#development)

```
composer install
php vendor/bin/grumphp run
```

Run mutation testing:

```
php vendor/bin/infection --threads=4
```

Contributing
------------

[](#contributing)

Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for branch strategy, commit conventions, and PR workflow.

License
-------

[](#license)

This project is released under the MIT License. See [LICENSE](LICENSE) for details and [CHANGELOG.md](CHANGELOG.md) for release history.

###  Health Score

43

—

FairBetter than 90% of packages

Maintenance92

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 50% 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 ~17 days

Total

3

Last Release

65d ago

PHP version history (2 changes)v1.0.0PHP ^8.4

v1.1.0PHP ^8.1

### Community

Maintainers

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

---

Top Contributors

[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (13 commits)")[![RubenJ01](https://avatars.githubusercontent.com/u/45236226?v=4)](https://github.com/RubenJ01 "RubenJ01 (13 commits)")

---

Tags

attributesdtomapperphpphp-library

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[jlawrence/eos

Parse and solve math equations without using 'eval()'.

1051.2M11](/packages/jlawrence-eos)[fomvasss/laravel-meta-tags

A package to manage SEO (meta-tags, xml-fields, etc.)

3129.5k](/packages/fomvasss-laravel-meta-tags)

PHPackages © 2026

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