PHPackages                             baconfy/factory-payload - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. baconfy/factory-payload

ActiveLibrary[Testing &amp; Quality](/categories/testing)

baconfy/factory-payload
=======================

Generate HTTP request payloads from Laravel Eloquent factories.

v1.2.1(4w ago)1309↓15.2%1AGPL-3.0-or-laterPHPPHP ^8.3CI passing

Since May 1Pushed 1w agoCompare

[ Source](https://github.com/baconfy/factory-payload)[ Packagist](https://packagist.org/packages/baconfy/factory-payload)[ RSS](/packages/baconfy-factory-payload/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (3)Versions (8)Used By (0)

 [![Prompt](https://raw.githubusercontent.com/baconfy/factory-payload/main/docs/presentation.jpg)](https://raw.githubusercontent.com/baconfy/factory-payload/main/docs/presentation.jpg)

[![Tests](https://github.com/baconfy/factory-payload/actions/workflows/tests.yml/badge.svg)](https://github.com/baconfy/factory-payload/actions/workflows/tests.yml)[![Latest Version](https://camo.githubusercontent.com/4e04e96f8a6ff716707b7bab5f7e67646d7c5ac186c65d7b4061132f4b2fcb06/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6261636f6e66792f666163746f72792d7061796c6f61642e737667)](https://packagist.org/packages/baconfy/factory-payload)[![License](https://camo.githubusercontent.com/bf048ba7ec7a6ed15837a6bd65ddd41e2a0f104a5b1838a6e294a60bf8a5a6db/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6261636f6e66792f666163746f72792d7061796c6f61642e737667)](https://packagist.org/packages/baconfy/factory-payload)[![Total Downloads](https://camo.githubusercontent.com/e407ca3699318e2efb4a6d4f0e195eb6c280f4774d1be90c60739a781c81f24a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6261636f6e66792f666163746f72792d7061796c6f61642e737667)](https://packagist.org/packages/baconfy/factory-payload)[![PHP Version](https://camo.githubusercontent.com/80b241836be9eda9603edd7c836779207e7a2cd532ef1956f4b023d87154df11/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6261636f6e66792f666163746f72792d7061796c6f61642e737667)](https://packagist.org/packages/baconfy/factory-payload)

Why?
----

[](#why)

When testing HTTP endpoints, you need request payloads that match the shape your endpoint expects, not the shape your model stores.

### The simple case

[](#the-simple-case)

Without this package:

```
$response = $this->postJson(route('posts.store'), [
    'title' => fake()->sentence(),
    'body' => fake()->paragraph(),
]);
```

With this package:

```
$response = $this->postJson(route('posts.store'), Post::factory()->payload());
```

One line. Self-documenting. Reusable across every test that hits this endpoint.

### When you need overrides

[](#when-you-need-overrides)

Sometimes you need to control specific fields, for example to test validation or assert against known values:

```
$response = $this->postJson(
    route('posts.store'),
    Post::factory()->payload(['title' => ''])
);

$response->assertJsonValidationErrors(['title']);
```

Overrides always pass through, even if the field isn't part of the model's stored attributes (useful for things like `password_confirmation`).

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

[](#installation)

```
composer require --dev baconfy/factory-payload
```

Requires PHP 8.3+ and Laravel 11, 12 or 13.

Usage
-----

[](#usage)

This package supports three equivalent ways to declare which attributes belong in the HTTP payload. Choose the style that best matches your project.

### Using `#[PayloadAttributes]`

[](#using-payloadattributes)

Declare the payload attributes directly on the factory class:

```
namespace Database\Factories;

use App\Models\Post;
use Baconfy\FactoryPayload\Attributes\PayloadAttributes;
use Illuminate\Database\Eloquent\Factories\Factory;

#[PayloadAttributes('title', 'body')]
class PostFactory extends Factory
{
    protected $model = Post::class;

    public function definition(): array
    {
        return [
            'title' => fake()->sentence(),
            'body' => fake()->paragraph(),
            'user_id' => User::factory(),
            'published_at' => now(),
        ];
    }
}
```

### Using `HasPayloadAttributes`

[](#using-haspayloadattributes)

Add the `HasPayloadAttributes` trait and define `$payloadAttributes` on your factory:

```
namespace Database\Factories;

use App\Models\Post;
use Baconfy\FactoryPayload\HasPayloadAttributes;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    use HasPayloadAttributes;

    protected $model = Post::class;

    /**
     * @var array
     */
    protected array $payloadAttributes = ['title', 'body'];

    public function definition(): array
    {
        return [
            'title' => fake()->sentence(),
            'body' => fake()->paragraph(),
            'user_id' => User::factory(),
            'published_at' => now(),
        ];
    }
}
```

Both examples produce the same payload in your tests:

```
$payload = Post::factory()->payload();
// ['title' => 'Lorem ipsum...', 'body' => 'Dolor sit amet...']
```

Notice how `user_id` and `published_at` are automatically excluded because they belong to persistence, not to the HTTP request.

### Using a DTO class

[](#using-a-dto-class)

If your project already declares request shapes through Data Transfer Objects (DTOs), you can resolve the payload shape directly from the DTO class. Useful when you have multiple endpoints (create, update, etc.) sharing the same model.

```
namespace App\Data;

class PostCreateData
{
    public static function keys(): array
    {
        return ['title', 'body'];
    }
}
```

```
$payload = Post::factory()->payload(PostCreateData::class);
// ['title' => 'Lorem ipsum...', 'body' => 'Dolor sit amet...']
```

The DTO resolution follows these rules:

1. If the class has a static `keys(): array` method, its return value is used as the whitelist (compatible with [`spatie/laravel-data`](https://github.com/spatie/laravel-data) and similar libraries).
2. Otherwise, falls back to the class's public properties via Reflection:

```
class PostUpdateData
{
    public ?string $title = null;
    public ?string $body = null;
}

$payload = Post::factory()->payload(PostUpdateData::class);
// ['title' => '...', 'body' => '...']
```

If the class doesn't exist, an `InvalidArgumentException` is thrown with a clear message.

> **Note:** When passing a DTO class, overrides are not supported in the same call. If you need both, use the array form: `payload(['title' => 'custom'])`.

### With Pest datasets

[](#with-pest-datasets)

Test multiple invalid scenarios in one go:

```
it('rejects invalid post payloads', function (array $overrides, string $errorField): void {
    $response = $this->postJson(
        route('posts.store'),
        Post::factory()->payload($overrides)
    );

    $response->assertStatus(422)->assertJsonValidationErrors([$errorField]);
})->with([
    'missing title' => [['title' => ''], 'title'],
    'missing body' => [['body' => ''], 'body'],
    'title too long' => [['title' => str_repeat('a', 300)], 'title'],
]);
```

Behavior
--------

[](#behavior)

The behavior below applies to all three ways of declaring payload attributes:

ScenarioResultNo payload attributes declaredReturns only the overrides`#[PayloadAttributes]` or `$payloadAttributes` declaredFilters `raw()` by whitelist, then merges overridesOverride key exists in whitelistOverride winsOverride key not in whitelistOverride still passes throughFactory has `count()` set`payload()` still returns a single arrayDTO class passed to `payload()`Resolves shape from `keys()` or public propertiesInvalid DTO class passedThrows `InvalidArgumentException`Testing
-------

[](#testing)

```
composer test
```

Credits
-------

[](#credits)

- [Renato Dehnhardt](https://github.com/rdehnhardt)
- [Josh Donnell](https://github.com/joshdonnell) — for adding the `#[PayloadAttributes]` attribute support
- [All contributors](https://github.com/baconfy/factory-payload/graphs/contributors)

License
-------

[](#license)

See [LICENSE](LICENSE) for details.

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance96

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 85.2% 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 ~3 days

Total

5

Last Release

28d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7077461?v=4)[Renato Dehnhardt](/maintainers/rdehnhardt)[@rdehnhardt](https://github.com/rdehnhardt)

---

Top Contributors

[![rdehnhardt](https://avatars.githubusercontent.com/u/7077461?v=4)](https://github.com/rdehnhardt "rdehnhardt (23 commits)")[![joshdonnell](https://avatars.githubusercontent.com/u/17536271?v=4)](https://github.com/joshdonnell "joshdonnell (4 commits)")

---

Tags

laravellaravel-frameworkpestpestphphttptestinglaravelfactorypayload

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/baconfy-factory-payload/health.svg)

```
[![Health](https://phpackages.com/badges/baconfy-factory-payload/health.svg)](https://phpackages.com/packages/baconfy-factory-payload)
```

###  Alternatives

[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.4k](/packages/larastan-larastan)[osteel/openapi-httpfoundation-testing

Validate HttpFoundation requests and responses against OpenAPI (3+) definitions

1202.1M7](/packages/osteel-openapi-httpfoundation-testing)[sti3bas/laravel-scout-array-driver

Array driver for Laravel Scout

971.6M5](/packages/sti3bas-laravel-scout-array-driver)[laravel-shift/factory-generator

Generate factories from existing models

49764.9k](/packages/laravel-shift-factory-generator)[imanghafoori/eloquent-mockery

Allows you to design your tests in an independent manner.

127637.9k2](/packages/imanghafoori-eloquent-mockery)[calebdw/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

15104.9k4](/packages/calebdw-larastan)

PHPackages © 2026

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