PHPackages                             factory-bot/factory-bot - 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. factory-bot/factory-bot

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

factory-bot/factory-bot
=======================

Fixtures replacement with a straightforward definition syntax

1.4.1(4y ago)734.8k↓41.5%2[1 issues](https://github.com/Godfather27/FactoryBot/issues)[2 PRs](https://github.com/Godfather27/FactoryBot/pulls)MITPHPPHP &gt;=5.4.0CI failing

Since Jun 19Pushed 2y ago1 watchersCompare

[ Source](https://github.com/Godfather27/FactoryBot)[ Packagist](https://packagist.org/packages/factory-bot/factory-bot)[ Docs](https://github.com/Godfather27/FactoryBot)[ RSS](/packages/factory-bot-factory-bot/feed)WikiDiscussions master Synced yesterday

READMEChangelog (7)Dependencies (3)Versions (8)Used By (0)

[![Version](https://camo.githubusercontent.com/2f6f169b886dceb60e8338e3d1bedcb10d77da936763bb7cb90f79dfb9bff1dd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f476f6466617468657232372f466163746f7279426f743f6c6162656c3d6c617465737425323076657273696f6e)](https://camo.githubusercontent.com/2f6f169b886dceb60e8338e3d1bedcb10d77da936763bb7cb90f79dfb9bff1dd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f476f6466617468657232372f466163746f7279426f743f6c6162656c3d6c617465737425323076657273696f6e) [![PHP Composer](https://github.com/Godfather27/FactoryBot/workflows/PHP%20Composer/badge.svg)](https://github.com/Godfather27/FactoryBot/workflows/PHP%20Composer/badge.svg) [![Coverage](https://camo.githubusercontent.com/334ff7bf8705d2b0186463d67c46fb87e13fdf3c0226b22c6205e0344134e032/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f476f6466617468657232372f466163746f7279426f74)](https://camo.githubusercontent.com/334ff7bf8705d2b0186463d67c46fb87e13fdf3c0226b22c6205e0344134e032/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f476f6466617468657232372f466163746f7279426f74) [![Maintainability](https://camo.githubusercontent.com/41df7ec457c257c87375b1cc1d52b287133adb751c143c203bf71bca06ae502c/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f65306638653864616536323037396631343164322f6d61696e7461696e6162696c697479)](https://camo.githubusercontent.com/41df7ec457c257c87375b1cc1d52b287133adb751c143c203bf71bca06ae502c/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f65306638653864616536323037396631343164322f6d61696e7461696e6162696c697479)

FactoryBot
==========

[](#factorybot)

This is inspired by thoughtbot's ruby [factory\_bot](https://github.com/thoughtbot/factory_bot).

FactoryBot is a fixtures replacement with a straightforward definition syntax, support for multiple build strategies (saved instances, unsaved instances), and support for multiple factories for the same class (user, admin\_user, and so on), including factory inheritance.

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Defining factories](#defining-factories)
- [Loading definitions](#loading-definitions)
- [Using factories](#using-factories)
- [Aliases](#aliases)
- [Dependent Attributes](#dependent-attributes)
- [Inheritance](#inheritance)
- [Relations](#relations)
    - [Single Relation](#single-relation)
    - [Many Relations](#many-relations)
    - [Cyclic Relation](#cyclic-relation)
    - [Shared Dependencies](#shared-dependencies)
- [Sequences](#sequences)
- [Custom Strategies](#custom-strategies)
- [Lifecycle Hooks](#lifecycle-hooks)
    - [Hook per Factory](#hook-per-factory)
    - [global Hook](#global-hook)
- [using FactoryBot with php faker](#using-factorybot-with-php-faker)

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

[](#installation)

Install the latest version with

```
    $ composer require factory-bot/factory-bot

```

Defining factories
------------------

[](#defining-factories)

Each factory has a name and a set of attributes. The name is used to guess the class of the object by default:

```
use FactoryBot\FactoryBot;

FactoryBot::define(
    UserModel::class,
    ["firstName" => "John", "lastName" => "Doe"]
);
```

It is also possible to explicitly specify the class:

```
use FactoryBot\FactoryBot;

FactoryBot::define(
    "Admin",
    ["firstName" => "John", "lastName" => "Doe"],
    ["class" => UserModel::class]
);
```

It is highly recommended that you have one factory for each class that provides the simplest set of attributes necessary to create an instance of that class. Other factories can be created through inheritance to cover common scenarios for each class.

Attempting to define multiple factories with the same name will overwrite the previously defined factory.

Loading definitions
-------------------

[](#loading-definitions)

The default path to define definitions is `tests/factories`. You can create a File for each Model you want to define a Factory for. For example you could create a `tests/factories/UserModel.php` file where you define a base Factory and different Factories extending from the base Factory.

Your file structure could look like this:

```
.
├── src
├── tests
│   ├── factories
│   │   ├── UserModel.php    # Factory definitions for UserModel
│   │   └── AccountModel.php # Factory definitions for AccountModel
│   ├── ... # tests
│   └── ... # tests
└── README.md

```

Before using the Factories in your test files you can load them by calling `FactoryBot::findDefinitions();`.

If you are using PHPUnit this can be done in your bootstrap file.

If you need to save your factories in a different location for your project, you can specify it by using `FactoryBot::setDefinitionsBasePath("your/path/factories/");`.

You also have the possibility to define your Factories inline and omit calling `findDefinitions`.

Using factories
---------------

[](#using-factories)

FactoryBot supports several different build strategies: `build`, `create`

```
use FactoryBot\FactoryBot;

# Returns a User instance that's not saved
FactoryBot::build(UserModel::class)

# Returns a saved User instance
FactoryBot::create(UserModel::class);
```

No matter which strategy is used, it's possible to override the defined attributes by passing an array:

```
# Build a User instance and override the first_name property
FactoryBot::build(UserModel::class, ["firstName" => "Jane"]);
```

Aliases
-------

[](#aliases)

FactoryBot allows you to define aliases to existing factories to make them easier to re-use. This could come in handy when, for example, your Post object has an author attribute that actually refers to an instance of a User class. While normally FactoryBot can infer the factory name from the association name, in this case it will look for an author factory in vain. So, alias your user factory so it can be used under alias names.

```
FactoryBot::define(
    UserModel::class,
    ["firstName" => "Jane"],
    ["aliases" => ["Author", "Commenter"]]
);

FactoryBot::define(
    PostModel::class,
    [
        "title" => "lorem ipsum!",
        "body" => "lorem ipsum dolor sit amet",
        "author" => FactoryBot::relation("Author")
    ]
);

FactoryBot::define(
    CommentModel::class,
    [
        "body" => "lorem ipsum dolor sit amet",
        "commenter" => FactoryBot::relation("Commenter")
    ]
);
```

Dependent Attributes
--------------------

[](#dependent-attributes)

Attributes can be based on the values of other attributes using the callable definition style. The callable gets passed in the partially hydrated model. The model gets hydrated with the specified params in order, so putting the email last enables us to access `firstName` and `lastName`.

```
FactoryBot::define(
    UserModel::class,
    [
        "firstName" => "John",
        "lastName" => "Doe",
        "email" => function ($model) {
            return strtolower(
                $model->getfirstName() . "." . $model->getLastName() . "@example.com"
            );
        }
    ]
);

FactoryBot::build(UserModel::class)->getEmail()
# > "john.doe@example.com"
```

Inheritance
-----------

[](#inheritance)

You can easily create multiple factories for the same class without repeating common attributes by nesting factories:

```
# Define a basic user
FactoryBot::define(
    UserModel::class,
    [
        "firstName" => "Jane",
        "lastName" => "Doe",
        "role" => "user"
    ]
);

# Extend the User Model as an Admin Factory
FactoryBot::extend("Admin", UserModel::class, ["role" => "admin"]);
```

As mentioned above, it's good practice to define a basic factory for each class with only the attributes required to create it. Then, create more specific factories that inherit from this basic parent. Factory definitions are still code, so keep them DRY.

Relations
---------

[](#relations)

It's possible to set up relationships within factories.

Relations default to using the same build strategy as their parent object:

```
FactoryBot::define(
    PostModel::class,
    ["author" => FactoryBot::relation("Author")]
);

$post = FactoryBot::create(PostModel::class);
$post->isNew();              # > false
$post->getAuthor()->isNew(); # > false

$post2 = FactoryBot::build(PostModel::class);
$post2->isNew();              # > true
$post2->getAuthor()->isNew(); # > true
```

### Single Relation

[](#single-relation)

Use the relation method from FactoryBot and provide the Factory which should be used.

```
FactoryBot::define(
    PostModel::class,
    [
        "title" => "lorem ipsum!",
        "body" => "lorem ipsum dolor sit amet",
        "author" => FactoryBot::relation("Author")
    ]
);
```

### Many Relations

[](#many-relations)

To generate has many relationships you can use the relations method:

```
FactoryBot::define(
    UserModel::class,
    ["posts" => FactoryBot::relations(PostModel::class, 2)]
);

$user = FactoryBot::build(UserModel::class);
$user->getPosts(); # > [PostModel, PostModel]
```

### Cyclic Relation

[](#cyclic-relation)

To generate cyclic relationships you should set children to `null` to avoid infinite children generation:

```
FactoryBot::define(
    UserModel::class,
    [
        "firstName" => "Jane",
        "lastName" => "Doe",
        "subordinate" => FactoryBot::relation(
            UserModel::class,
            ["subordinate" => null]
        )
    ]
);

$user = FactoryBot::build(UserModel::class);
$user->getSubordinate(); # > UserModel
$user->getSubordinate()->getSubordinate(); # > null
```

### Shared Dependencies

[](#shared-dependencies)

If you want to share dependend instances in your Factory definition, you can use the closure style definition. This could be useful for advanced usecases, but adds complexity to the definition so it is recommended to use this definition style on extended Factories only.

```
FactoryBot::extend(
    "Supervisor",
    UserModel::class,
    [
        "company" => FactoryBot::relation(CompanyModel::class),
        "subordinate" => function ($user, $buildStrategy) {
            return FactoryBot::relation(
                UserModel::class,
                [
                    "company" => $user->getCompany(), # subordinate works in the same company as its supervisor
                    "subordinate" => null
                ]
            )(null, $buildStrategy); # call the relation with null and the parent's build strategy
        }
    ]
);
```

Keep in mind you can also manually share models when creating test data. This also helps developers understand dependencies for a test case more easily.

```
$company = FactoryBot::build(CompanyModel::class);
$subordinate = FactoryBot::build(UserModel::class, ["subordinate" => null, "company" => $company]);
$user = FactoryBot::build(UserModel::class, ["subordinate" => $subordinate, "company" => $company]);
```

Sequences
---------

[](#sequences)

Unique values in a specific format (for example, e-mail addresses) can be generated using sequences.

The default implementation will generate a sequence of numbers, like the classic auto increment in SQL.

```
FactoryBot::define(UserModel::class, ["id" => FactoryBot::sequence()]);
```

To implement your own sequence method pass a method which generates a unique sequence value per call.

```
FactoryBot::define(
    UserModel::class,
    [
        "email" => FactoryBot::sequence(function($num, $model) {
            return "user" . $num . "@example.com";
        })
    ]
);

$user = FactoryBot::build(UserModel::class);
$user->getEmail() # > "user1@example.com"
```

Custom Strategies
-----------------

[](#custom-strategies)

The capability of FactoryBot can be extended by implementing custom Strategies.

A Strategy must implement the `FactoryBot/Strategies/StrategyInterface` Interface. The Interface defines two methods. `beforeCompile` is a method which gets called before the hydration step is executed. The second method is `result` which gets called after the hydration step, here you can do some changes to the instance before returning it.

In this example the Strategy will return the instance as a JSON string.

```
use FactoryBot\FactoryBot;
use FactoryBot\Strategies\StrategyInterface;

class JsonStrategy implements StrategyInterface
{
    public static function beforeCompile($factory)
    {
        // we call $factory->notify to ensure the Factories "before" Hooks get called
        $factory->notify("before");
    }

    public static function result($factory, $instance)
    {
        // we call $factory->notify to ensure the Factories "after" Hooks get called
        $factory->notify("after");

        $result = self::getPropertiesArray($instance);

        return json_encode($result);
    }

    public static function getPropertiesArray($instance)
    {
        $instanceArray = (array) $instance;
        $result = [];
        foreach ($instanceArray as $keyWithVisibility => $value) {
            $keySegments = explode("\0", $keyWithVisibility);
            $keyWithoutVisibility = end($keySegments);
            $result[$keyWithoutVisibility] = $value;
        }
        return $result;
    }
}

FactoryBot::registerStrategy("json", JsonStrategy::class);
FactoryBot::define(UserModel::class, ["firstName" => "Jane"]);
FactoryBot::json(UserModel::class); # > '{"id":null,"firstName":"Jane",...,"subordinate":null,"new":true}'
```

Lifecycle Hooks
---------------

[](#lifecycle-hooks)

FactoryBot provides 6 different hooks to inject custom code.

- `before` - called before building or creating an instance.
- `after` - called after building or creating an instance.
- `beforeCreate` - called before creating an instance.
- `afterCreate` - called after creating an instance.
- `beforeBuild` - called before building an instance.
- `afterBuild` - called after building an instance.

Factories can also define any number of the same kind of hook. These hooks will be executed in the order they are specified.

### Hook per Factory

[](#hook-per-factory)

On the definition of a Factory you can register a lifecycle hook, which only gets executed on the Factory where it is defined.

Example:

```
$logger = new Logger();

FactoryBot::define(
    UserModel::class,
    ["name" => "Jane Doe"],
    ["hooks" => [
        FactoryBot::hook("afterCreate", function ($instance) use ($logger) {
            $logger->debug("created an UserModel instance: $instance->getName()");
        })
    ]]
);

$user = FactoryBot::create(UserModel::class); # logger output > "created an UserModel instance: Jane Doe"
```

### global Hook

[](#global-hook)

A Hook can also be registered for all Factories.

```
$logger = new Logger();

FactoryBot::registerGlobalHook("afterCreate", function ($instance) use ($logger) {
    $class = get_class($instance);
    $logger->debug("created an $class instance");
});

FactoryBot::define(UserModel::class);
FactoryBot::define(PostModel::class);

$user = FactoryBot::create(UserModel::class); # logger output > "created an UserModel instance"
$post = FactoryBot::create(PostModel::class); # logger output > "created an PostModel instance"
```

A Hook can also be removed again.

```
$logger = new Logger();

$hook = FactoryBot::registerGlobalHook("afterCreate", function ($instance) use ($logger) {
    $class = get_class($instance);
    $logger->debug("created an $class instance");
});

FactoryBot::define(UserModel::class);
FactoryBot::define(PostModel::class);

$user = FactoryBot::create(UserModel::class); # logger output > "created an UserModel instance"
$post = FactoryBot::create(PostModel::class); # logger output > "created an PostModel instance"

FactoryBot::removeGlobalHook($hook);

$user = FactoryBot::create(UserModel::class); # no logger output
$post = FactoryBot::create(PostModel::class); # no logger output
```

using FactoryBot with php faker
-------------------------------

[](#using-factorybot-with-php-faker)

Faker methods should be wrapped by a callable. This way the faker method will be called during the build process. Otherwise the faker method will be called on definition and all instances will have the same value.

using a local instance of faker:

```
use Faker\Factory;
use FactoryBot\FactoryBot;

$faker = Factory::create('at_AT');
FactoryBot::define(
    UserModel::class,
    [
        "name" => "Jane Doe",
        # local variables have to be injected using use
        "street" => function () use ($faker) { return $faker->streetName(); },
    ]
);
```

using an instance variable:

```
use Faker\Factory;
use FactoryBot\FactoryBot;

class FactorySetup
{
    /**
     * faker generator
    */
    private $faker;

    public function __construct()
    {
        $this->faker = Factory::create('at_AT');
        $this->setUpUserFactory()
    }

    public function setUpUserFactory()
    {
        FactoryBot::define(
            UserModel::class,
            [
                "name" => "Jane Doe",
                # instance variables can be accessed without use
                "street" => function () { return $this->faker->streetName(); },
            ]
        );
    }
}
```

###  Health Score

32

—

LowBetter than 69% of packages

Maintenance17

Infrequent updates — may be unmaintained

Popularity33

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity56

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

Recently: every ~117 days

Total

7

Last Release

1731d ago

### Community

Maintainers

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

---

Top Contributors

[![zelle7](https://avatars.githubusercontent.com/u/2727205?v=4)](https://github.com/zelle7 "zelle7 (1 commits)")

---

Tags

testingfactoryFixturedatabotfactorygirlfactory\_botfactorybotfactoryboy

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[nelmio/alice

Expressive fixtures generator

2.5k45.2M166](/packages/nelmio-alice)[zenstruck/foundry

A model factory library for creating expressive, auto-completable, on-demand dev/test fixtures with Symfony and Doctrine.

79613.7M149](/packages/zenstruck-foundry)[league/factory-muffin

The goal of this package is to enable the rapid creation of objects for the purpose of testing.

54114.6M53](/packages/league-factory-muffin)[laracasts/testdummy

Easy test stubs

4671.4M38](/packages/laracasts-testdummy)[league/factory-muffin-faker

The goal of this package is to wrap faker to make it super easy to use with factory muffin.

4412.3M28](/packages/league-factory-muffin-faker)[breerly/factory-girl-php

Fixture replacement for focused and readable tests - A PHP port of Thoughtbot's Ruby Factory Girl

111243.0k2](/packages/breerly-factory-girl-php)

PHPackages © 2026

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