PHPackages                             markhuot/data - 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. markhuot/data

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

markhuot/data
=============

Data objects

1.0.5(3y ago)08941GPL-3.0-or-laterPHP

Since Oct 25Pushed 3y ago1 watchersCompare

[ Source](https://github.com/markhuot/data)[ Packagist](https://packagist.org/packages/markhuot/data)[ RSS](/packages/markhuot-data/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (8)Versions (8)Used By (1)

Simple data objects
===================

[](#simple-data-objects)

Data (or value) objects can be used to represent data that may not otherwise have a strict class in your application. For example, POST data coming from a web request or JSON data coming from an API call. In these situations you may want a strongly typed version of the data but not want to write all the boilerplate to cast the data from the source to your data object.

This package handles all that boilerplate for you and aims to cover 80% of the most common use cases with the ability to extend the package should you need more specific transformations.

At it's most basic level the package is a transformer from your source representation (usually loosely typed) in to the target representation (more strongly typed). It looks like this (seriously).

```
class Repository {
    public int $id;
    public string $name;
    public string $fullName;
    public array $topics;
    public bool $private;
}
```

The goal of this package is to be able to layer this package on top of your existing data objects without needing much (if any) customization. It works off attribute labels and tries to infer as much through convention as possible.

To convert source data in to your data object you'll call `->fill($data)` on the data builder.

```
(new Data(new MyAwesomeObject))->fill($data)->get();
```

When you call `->fill($data)` the package will use introspection to determine how the source `$data` maps to the properties in the `Repository` object. By default there is *no* mapping and it will blindly look for source fields like `id` and push them in to the destination property of `->id`.

When the mapping is not 1:1 and you need to more control over the field naming you can use the `MapFrom` attribute to help the transformer along.

```
use markhuot\data\attributes\MapFrom;

class Repository {
    public int $id;
    public string $name;

    #[MapFrom('full_name')]
    public string $fullName;
}
```

That will pull the `full_name` field from the source and drop it in to the `->fullName` property in the destination. If your conversion is snake case to camel case there is a convent helper to do just that,

```
use markhuot\data\attributes\MapFrom;

class Repository {
    public int $id;
    public string $name;

    #[MapFrom(MapFrom::SNAKE)]
    public string $fullName;
}
```

If you find yourself using identical `MapFrom` annotations several times over you can also apply the attribute to the class to have all property names converted in the same way,

```
use markhuot\data\attributes\MapFrom;

#[MapFrom(MapFrom::SNAKE)]
class Repository {
    public int $id;
    public string $name;
    public string $fullName;
}
```

In example all fields in the `Repository` class will be converted during transformation. `id` will remain `->id`, `name` will remain `->name` but `full_name` will automatically map to `->fullName`.

Nested maps
-----------

[](#nested-maps)

By default nested properties will be mapped based on the type hint. The typehit can either come from PHP or the docblock depending on your needs. For single object nesting you can use native PHP type hints like this,

```
class Repository {
    public int $id;
    public string $name;
    public string $fullName;
    public Owner $owner;
    public array $topics;
    public bool $private;
}

class Owner {
    public int $id;
    public string $login;
    public string $avatarUrl;
}
```

This will map the source data `['owner' => ['id' => 1, 'login' => 'foo']]` over to a `Repository` with an `->owner` property that is correctly set to an `Owner` instance with `->id` and `->login` set on the `Owner` instance.

For more advanced mappings you can use a docblock to define properties that PHP doesn't yet understand. For example,

```
class Release {
    public int $id;
    public string $tagName;

    /** @var Asset[] */
    public array $assets;
}

class Asset {
    public int $id;
    public string $name;
    public string $url;
}
```

This will correctly read that `->assets` expects to be an array of assets and will try to transform the source in to an array of objects. It would work with the following source data,

```
{
    "id": "1",
    "tag_name": "1.0.0",
    "assets": [
        {
            "id": "1",
            "name": "1.0.0.zip",
            "url" "..."
        },
        {
            "id": "2",
            "name": "1.0.1.zip",
            "url" "..."
        }
    ]
}
```

Validation
----------

[](#validation)

Because many times strict typing isn't enough to ensure the data is correct you can also use the [Symfony validation component](https://symfony.com/doc/current/validation.html) to validate the data after the `->fill()` process.

```
use Symfony\Component\Validator\Constraints as Assert;

class CreateBlogPostData {
    #[Assert\NotNull]
    public int $authorId;

    #[Assert\NotBlank]
    public string $title;

    #[Assert\Regex('/[a-z0-9_-]+/')]
    public ?string $slug;
}

$data = (new Data(new CreateBlogPostData))->fill($_POST)->validate()->get();
```

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity51

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

Total

6

Last Release

1290d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2628c4f6f6afddfe0b861cee15ae5b18c673d874f68786ebd1d01bba2dd6bdfb?d=identicon)[markhuot](/maintainers/markhuot)

---

Top Contributors

[![markhuot](https://avatars.githubusercontent.com/u/48975?v=4)](https://github.com/markhuot "markhuot (21 commits)")

###  Code Quality

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/markhuot-data/health.svg)

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

###  Alternatives

[cognesy/instructor-php

The complete AI toolkit for PHP: unified LLM API, structured outputs, agents, and coding agent control

310107.9k1](/packages/cognesy-instructor-php)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

7310.3k29](/packages/open-dxp-opendxp)[netgen/layouts-core

Netgen Layouts enables you to build and manage complex web pages in a simpler way and with less coding. This is the core of Netgen Layouts, its heart and soul.

3689.4k10](/packages/netgen-layouts-core)[chameleon-system/chameleon-base

The Chameleon System core.

1026.5k3](/packages/chameleon-system-chameleon-base)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

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