PHPackages                             zero-to-prod/data-model-factory - 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. zero-to-prod/data-model-factory

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

zero-to-prod/data-model-factory
===============================

Build a Factory for Anything

v71.8.0(8mo ago)28.0k↓16.7%[1 PRs](https://github.com/zero-to-prod/data-model-factory/pulls)4MITPHPPHP &gt;=7.1.0CI passing

Since Oct 15Pushed 8mo ago1 watchersCompare

[ Source](https://github.com/zero-to-prod/data-model-factory)[ Packagist](https://packagist.org/packages/zero-to-prod/data-model-factory)[ Docs](https://github.com/zero-to-prod/data-model-factory)[ Fund](https://github.com/sponsors/zero-to-prod)[ RSS](/packages/zero-to-prod-data-model-factory/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (29)Used By (4)

Zerotoprod\\DataModelFactory
============================

[](#zerotoproddatamodelfactory)

[![](art/logo.png)](art/logo.png)

[![Repo](https://camo.githubusercontent.com/9a90a3efeee26aed7d7f2feee9cd84566a26f9c362cc773b184d076210906e1c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6769746875622d677261793f6c6f676f3d676974687562)](https://github.com/zero-to-prod/data-model-factory)[![tests](https://camo.githubusercontent.com/b4d5a2a2393e3dc54d93ed1d3c8c20b8621ff8813b46ab5d51b3dbc9b8b1e9ee/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72792f746573742e796d6c3f6c6162656c3d74657374)](https://github.com/zero-to-prod/data-model-factory/actions)[![GitHub Actions Workflow Status](https://camo.githubusercontent.com/ba4cb0a2312294c391b7aeee79f7251970b15743b7cde5d4296ef9dd80166a02/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72792f6261636b77617264735f636f6d7061746962696c6974792e796d6c3f6c6162656c3d6261636b77617264735f636f6d7061746962696c697479)](https://github.com/zero-to-prod/data-model-factory/actions)[![Packagist Downloads](https://camo.githubusercontent.com/6096b947d0bb2f18453881a4b8fe589c3e24993b41e18c770a72442c7d8fbaa7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72793f636f6c6f723d626c7565)](https://packagist.org/packages/zero-to-prod/data-model-factory/stats)[![php](https://camo.githubusercontent.com/4c8899197b8069241b483b4f6e75df8e8dfc5c3d8f0eaa337f2d58d0aebaf4d1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72792e7376673f636f6c6f723d707572706c65)](https://packagist.org/packages/zero-to-prod/data-model-factory/stats)[![Packagist Version](https://camo.githubusercontent.com/6699fc3d45766b56faa640feafee11016296d69b779c88912bd425c4cb991bd4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72793f636f6c6f723d663238643161)](https://packagist.org/packages/zero-to-prod/data-model-factory)[![License](https://camo.githubusercontent.com/717b235f44c9f3dda374651aee3f91d3c66f12384980b534906ad31eea143138/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72793f636f6c6f723d70696e6b)](https://github.com/zero-to-prod/data-model-factory/blob/main/LICENSE.md)[![wakatime](https://camo.githubusercontent.com/57d9d2690e0e544ca4becf1e9e849cec21e35512de13637e6bc81489e85de68a/68747470733a2f2f77616b6174696d652e636f6d2f62616467652f6769746875622f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72792e737667)](https://wakatime.com/badge/github/zero-to-prod/data-model-factory)[![Hits-of-Code](https://camo.githubusercontent.com/fd0cf45ccbe451e2d40dd63e9397dbbacfa8bc77a16525dafe488d746296ebda/68747470733a2f2f686974736f66636f64652e636f6d2f6769746875622f7a65726f2d746f2d70726f642f646174612d6d6f64656c2d666163746f72793f6272616e63683d6d61696e)](https://hitsofcode.com/github/zero-to-prod/data-model-factory/view?branch=main)

Contents
--------

[](#contents)

- [Introduction](#introduction)
- [Requirements](#requirements)
- [Installation](#installation)
- [Documentation Publishing](#documentation-publishing)
    - [Automatic Documentation Publishing](#automatic-documentation-publishing)
- [Additional Packages](#additional-packages)
- [Usage](#usage)
    - [Custom Class Instantiation](#custom-class-instantiation)
    - [The `set()` Method](#the-set-method)
    - [The `merge()` Method](#the-merge-method)
    - [The `context()` Method](#the-context-method)
- [Local Development](./LOCAL_DEVELOPMENT.md)
- [Contributing](#contributing)

Introduction
------------

[](#introduction)

This package is a fresh take on how to set the state of your DTOs in a simple and delightful way.

The API is takes some hints from Laravel's Eloquent [Factories](https://laravel.com/docs/11.x/eloquent-factories), but adds some niceties such as setting state via dot syntax and using the [set()](#the-set-method) helper method on the fly.

This package does not require any other dependencies, allowing you to make a factory for anything.

The examples use the [DataModel](https://github.com/zero-to-prod/data-model) trait, making easier to build your DTOs, but it is not required.

Requirements
------------

[](#requirements)

- PHP 7.1 or higher.

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

[](#installation)

Install the package via Composer:

```
composer require zero-to-prod/data-model-factory
```

This will add the package to your project’s dependencies and create an autoloader entry for it.

Documentation Publishing
------------------------

[](#documentation-publishing)

You can publish this README to your local documentation directory.

This can be useful for providing documentation for AI agents.

This can be done using the included script:

```
# Publish to default location (./docs/zero-to-prod/data-model-factory)
vendor/bin/zero-to-prod-data-model-factory

# Publish to custom directory
vendor/bin/zero-to-prod-data-model-factory /path/to/your/docs
```

#### Automatic Documentation Publishing

[](#automatic-documentation-publishing)

You can automatically publish documentation by adding the following to your `composer.json`:

```
{
  "scripts": {
    "post-install-cmd": [
      "zero-to-prod-data-model-factory"
    ],
    "post-update-cmd": [
      "zero-to-prod-data-model-factory"
    ]
  }
}
```

### Additional Packages

[](#additional-packages)

- [DataModel](https://github.com/zero-to-prod/data-model): Transform data into a class.
- [DataModelHelper](https://github.com/zero-to-prod/data-model-helper): Helpers for a `DataModel`.
- [Transformable](https://github.com/zero-to-prod/transformable): Transform a `DataModel` into different types.

Usage
-----

[](#usage)

This example makes use of the [DataModel](https://github.com/zero-to-prod/data-model) trait to instantiate the `User` class.

You can install the DataModel package like this:

```
composer require zero-to-prod/data-model
```

If you don't want to use this trait, you can [customize the class instantiation](#custom-class-instantiation) this way.

1. Include the Factory trait in your factory class.
2. Set the `$model` property to the class you want to instantiate.
3. Implement a `definition()` method that returns an array of default values.
4. NOTE: The `$this->state()` method accepts dot syntax, arrays, or a callback.

```
class User
{
    use \Zerotoprod\DataModelFactory\DataModel;

    public $first_name;
    public $last_name;
    public $address;

    public static function factory(array $context = []): UserFactory
    {
        return new UserFactory($context);
    }
}

class UserFactory
{
    use \Zerotoprod\DataModelFactory\DataModelFactory;

    /* This is the class to be instantiated with the make() method */
    protected $model = User::class;

    protected function definition(): array
    {
        return [
            'first_name' => 'John',
            'last_name' => 'N/A',
            'address' => [
                'street' => 'Memory Lane'
            ]
        ];
    }

    public function setStreet(string $value): self
    {
        /** Dot Syntax */
        return $this->state('address.street', $value);
    }

    public function setFirstName(string $value): self
    {
        /** Array Syntax */
        return $this->state(['first_name' => $value]);
    }

    public function setLastName(): self
    {
        /** Closure Syntax */
        return $this->state(function ($context) {
            return ['first_name' => $context['last_name']];
        });
    }

    /* Optionally implement for better static analysis */
    public function make(array $context = []): User
    {
        return $this->instantiate($context);
    }
}

$User = UserFactory::factory([User::last_name => 'Doe'])
            ->setFirstName('Jane')
            ->make();

User::factory([User::last_name => 'Doe'])->make(); // Also works for this example

echo $User->first_name; // 'Jane'
echo $User->last_name;  // 'Doe'
```

### Custom Class Instantiation

[](#custom-class-instantiation)

To customize instantiation, override the `make()` method.

```
class User
{
    public function __construct(public string $fist_name, public string $last_name)
    {
    }
}

class UserFactory
{
    use \Zerotoprod\DataModelFactory\DataModelFactory;

    private function definition(): array
    {
        return [
            'first_name' => 'John',
            'last_name' => 'Doe',
        ];
    }

    private function make(): User
    {
        return new User($this->context['first_name'], $this->context['last_name']);
    }
}

$User = UserFactory::factory()->make();

echo $User->first_name; // 'Jane'
echo $User->last_name;  // 'Doe'
```

### The `set()` Method

[](#the-set-method)

You can use the `set()` helper method to fluently modify the state of your model in a convenient way.

This is a great way to modify a model without having to implement a method in the factory.

```
$User = User::factory()
            ->set('first_name', 'John')
            ->set(['last_name' => 'Doe'])
            ->set(function ($context) {
                return ['surname' => $context['last_name']];
            })
            ->set('address.postal_code', '46789') // dot syntax for nested values
            ->make();

echo $User->first_name;             // John
echo $User->last_name;              // Doe
echo $User->surname;                // Doe
echo $User->address->postal_code;   // 46789
```

### The `merge()` Method

[](#the-merge-method)

Sometimes it is useful to merge new values into the current context of the factory.

Use the `merge()` method to merge any new values and update the factory context.

```
class UserFactory
{
    use \Zerotoprod\DataModelFactory\DataModelFactory;

    private function definition(): array
    {
        return [
            'first_name' => 'John',
            'last_name' => 'Doe',
        ];
    }
}

$User = UserFactory::factory()
    ->merge(['first_name' => 'Jane'])
    ->make();

echo $User->first_name; // 'Jane'
echo $User->last_name;  // 'Doe'
```

### The `context()` Method

[](#the-context-method)

Use the `context()` method to get the context of the factory.

```
class UserFactory
{
    use \Zerotoprod\DataModelFactory\DataModelFactory;

    private function definition(): array
    {
        return [
            'first_name' => 'John',
            'last_name' => 'Doe',
        ];
    }
}

$User = UserFactory::factory()->context();

echo $User['first_name']; // 'John'
echo $User['last_name'];  // 'Doe'
```

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

[](#contributing)

Contributions, issues, and feature requests are welcome! Feel free to check the [issues](https://github.com/zero-to-prod/data-model-factory/issues) page if you want to contribute.

1. Fork the repository.
2. Create a new branch (`git checkout -b feature-branch`).
3. Commit changes (`git commit -m 'Add some feature'`).
4. Push to the branch (`git push origin feature-branch`).
5. Create a new Pull Request.

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance64

Regular maintenance activity

Popularity26

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity44

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

Recently: every ~1 days

Total

26

Last Release

250d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/502649f05d36c87d494988bd99193a4d908d345335d99c080928a726277371f5?d=identicon)[zero-to-prod](/maintainers/zero-to-prod)

---

Top Contributors

[![zero-to-prod](https://avatars.githubusercontent.com/u/61474950?v=4)](https://github.com/zero-to-prod "zero-to-prod (27 commits)")

---

Tags

datamodeldtofactoryphpzero-to-proddata-model-factory

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/zero-to-prod-data-model-factory/health.svg)

```
[![Health](https://phpackages.com/badges/zero-to-prod-data-model-factory/health.svg)](https://phpackages.com/packages/zero-to-prod-data-model-factory)
```

###  Alternatives

[zero-to-prod/data-model

Transforms Data into Type-Safe DTOs.

14226.2k32](/packages/zero-to-prod-data-model)

PHPackages © 2026

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