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

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

league/factory-muffin
=====================

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

v3.3.0(5y ago)53713.6M↑18.3%73[17 issues](https://github.com/thephpleague/factory-muffin/issues)[8 PRs](https://github.com/thephpleague/factory-muffin/pulls)20MITPHPPHP &gt;=5.4.0

Since Jan 31Pushed 2y ago18 watchersCompare

[ Source](https://github.com/thephpleague/factory-muffin)[ Packagist](https://packagist.org/packages/league/factory-muffin)[ Docs](http://factory-muffin.thephpleague.com/)[ GitHub Sponsors](https://github.com/GrahamCampbell)[ Fund](https://tidelift.com/funding/github/packagist/league/factory-muffin)[ RSS](/packages/league-factory-muffin/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (4)Versions (36)Used By (20)

Factory Muffin 3.3
==================

[](#factory-muffin-33)

[![StyleCI Status](https://camo.githubusercontent.com/3fc8615c3afe252466fe82618b8be1cd128b2e201cc4dba1804bfc58c18a3e25/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f373933303436342f736869656c64)](https://github.styleci.io/repos/7930464)[![Build Status](https://camo.githubusercontent.com/08b44cc9ed30ebc4912e7e9e26bb6dd5491eb2047e40793c4cc93dd09f7e0b4e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f7468657068706c65616775652f666163746f72792d6d756666696e2f54657374733f6c6162656c3d5465737473267374796c653d666c61742d737175617265)](https://github.com/thephpleague/factory-muffin/actions?query=workflow%3ATests)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Latest Version](https://camo.githubusercontent.com/01039590a77657d2529a04083ff88b029cf008232cf20eda6a3ff304bdf88cea/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f7468657068706c65616775652f666163746f72792d6d756666696e2e7376673f7374796c653d666c61742d737175617265)](https://github.com/thephpleague/factory-muffin/releases)[![Total Downloads](https://camo.githubusercontent.com/476d272141ac9bed07ddaead19f6c96ca82a52a96a3ba75424c32bfc3969aa3d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c65616775652f666163746f72792d6d756666696e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/league/factory-muffin)

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

It's basically a "[factory\_girl](https://github.com/thoughtbot/factory_girl)", simplified for use with PHP.

Installing
----------

[](#installing)

[PHP](https://php.net) 5.4+ and [Composer](https://getcomposer.org) are required.

In your composer.json, simply add `"league/factory-muffin": "^3.3"` to your `"require-dev"` section:

```
{
    "require-dev": {
        "league/factory-muffin": "^3.3"
    }
}
```

[Faker](https://github.com/fzaninotto/Faker) support is provided by [Factory Muffin Faker](https://github.com/thephpleague/factory-muffin-faker). If you want to enable faker support, then you need to add `"league/factory-muffin-faker": "^2.3"` too:

```
{
    "require-dev": {
        "league/factory-muffin": "^3.3",
        "league/factory-muffin-faker": "^2.3"
    }
}
```

Upgrading
---------

[](#upgrading)

It maybe be useful for existing users to check out the [upgrade guide](UPGRADING.md).

Usage
-----

[](#usage)

### Introduction

[](#introduction)

This is the usage guide for Factory Muffin 3.0. Within this guide, you will see "the `xyz` function can be called". You should assume that these functions should be called on an instance of `League\FactoryMuffin\FactoryMuffin`; you should keep track of this instance yourself, and you can of course have multiple instances of this class for maximum flexibility. For simplicities sake, many of our examples include a `$fm` variable. This variable will actually be made available when files are required using the `loadFactories` function.

### Model Definitions

[](#model-definitions)

You can define model factories using the `define` function. You may call it like this: `$fm->define('Fully\Qualifed\ModelName')->addDefinitions('foo', 'bar')`, where `foo` is the name of the attribute you want set on your model, and `bar` describes how you wish to generate the attribute. You may also define multiple attributes at once like this: `$fm->define('Fully\Qualifed\ModelName')->setDefinitions('foo', 'bar')`. Note that both functions append to the internal attributes definition array rather than replacing it. Please see the generators section for more information on how this works.

You can also define multiple different model definitions for your models. You can do this by prefixing the model class name with your "group" followed by a colon. This results in you defining your model like this: `$fm->define('myGroup:Fully\Qualifed\ModelName')->addDefinitions('bar', 'baz')`. You don't have to entirely define your model here because we will first look for a definition without the group prefix, then apply your group definition on top of that definition, overriding attribute definitions where required. Note that if you want to use group prefixes, you *must* also create a definition without the group prefix as well.

We have provided a nifty way for you to do this in your tests. PHPUnit provides a `setupBeforeClass` function. Within that function you can call `$fm->loadFactories(__DIR__ . '/factories');`, and it will include all files in the factories folder. Within those PHP files, you can put your definitions (all your code that calls the define function).

The `loadFactories` function will recurse through all sub-folders of the path you specify when searching for factory files, except for hidden folders (i.e. starting with a .) which will be ignored. It will also throw a `League\FactoryMuffin\Exceptions\DirectoryNotFoundException` exception if the factories directory you specify is not found.

### Creation/Instantiation Callbacks

[](#creationinstantiation-callbacks)

You may optionally specify a callback to be executed on model creation/instantiation using the `setCallback` function, like this: `$fm->define('MyModel')->setCallback(function ($object, $saved) {})`. We will pass your model instance as the first parameter to the callback and a boolean as the second parameter. The boolean will be `true` if the model is being persisted to the database (the create function was used), and `false` if it's not being persisted (the instance function was used). We're using the `isPendingOrSaved` function under the hood here. Note that if you specify a callback and use the `create` function, we will try to save your model to the database both before and after we execute the callback.

### Generators

[](#generators)

#### Callable

[](#callable)

The callable generator can be used if you want a more custom solution. Whatever you return from your closure, or valid callable, will be set as the attribute. The closure/callable will be called with the same parameters as creation/instantiation callbacks described above: an instance of your model as the first parameter (to give you even more flexibility to modify it as you wish) and a boolean indicating if the model is being persisted to the database. In the following examples, we will go through using a closure, or callable, and then how to use faker to generate attributes.

##### Example 1

[](#example-1)

As you can see from this example, the ability to use a closure to generate attributes can be so useful and flexible. Here we use it to generate a slug based on the initially randomly generated 5 word long title.

```
$fm->define('MyModel')->setDefinitions([
    'title' => Faker::sentence(5),
    'slug' => function ($object, $saved) {
        $slug = preg_replace("/[^a-zA-Z0-9\/_|+ -]/", '', $object->title);
        $slug = strtolower(trim($slug, '-'));
        $slug = preg_replace("/[\/_|+ -]+/", '-', $slug);

        return $slug;
    },
]);
```

##### Example 2

[](#example-2)

This will set the `foo` attribute to whatever calling `MyModel::exampleMethod($object, $saved)` returns.

```
$fm->define('MyModel')->setDefinitions([
    'foo' => 'MyModel::exampleMethod',
]);
```

##### Example 3

[](#example-3)

There is a simple example of setting a few different attributes using our faker wrapper.

```
use League\FactoryMuffin\Faker\Facade as Faker;

$fm->define('MyModel')->setDefinitions([
    'foo'    => Faker::word(),          // Set the foo attribute to a random word
    'name'   => Faker::firstNameMale(), // Set the name attribute to a random male first name
    'email'  => Faker::email(),         // Set the email attribute to a random email address
    'body'   => Faker::text(),          // Set the body attribute to a random string of text
    'slogan' => Faker::sentence(),      // Set the slogan attribute to a random sentence
]);
```

##### Example 4

[](#example-4)

This will set the `age` attribute to a random number between 20 and 40.

```
use League\FactoryMuffin\Faker\Facade as Faker;

$fm->define('MyModel')->setDefinitions([
    'age' => Faker::numberBetween(20, 40),
]);
```

##### Example 5

[](#example-5)

This will set the `name` attribute to a random female first name. Because we've called the `unique` method first, the attribute should be unique between all your generated models. Be careful with this if you're generating lots models because we might run out of unique items. Also, note that calling `Faker::setLocale('whatever')` will reset the internal unique list.

```
use League\FactoryMuffin\Faker\Facade as Faker;

$fm->define('MyModel')->addDefinition('name', Faker::unique()->firstNameFemale());
```

##### Example 6

[](#example-6)

This will set the `profile_pic` attribute to a random image url of dimensions 400 by 400. Because we've called the `optional` method first, not all the generated models will have an image url set; sometimes we will return null.

```
use League\FactoryMuffin\Faker\Facade as Faker;

$fm->define('MyModel')->addDefinition('profile_pic', Faker::optional()->imageUrl(400, 400));
```

##### More

[](#more)

Check out the [faker library](https://github.com/fzaninotto/Faker) itself to see all the available methods. There are far too many to cover in the documentation here, and far too many for them to cover in their documentation too. Note that you can fiddle with the underlying faker instance through the public methods on our faker class if you want.

#### Factory

[](#factory)

The factory generator can be useful for setting up relationships between models. The factory generator will return the model id of the model you ask it to generate.

##### Example 1

[](#example-1-1)

When we create a Foo object, we will find that the Bar object will been generated and saved too, and it's id will be assigned to the `bar_id` attribute of the Foo model.

```
$fm->define('Foo')->addDefinition('bar_id', 'factory|Bar');

$fm->define('Bar')->addDefinition('baz', Faker::date('Y-m-d'));
```

### Creating And Seeding

[](#creating-and-seeding)

The `create` function will create and save your model, and will also save anything you generate with the `Factory` generator too. If you want to create multiple instances, check out the seed `seed` function, which accepts an additional argument at the start which is the number of models to generate in the process. The `seed` function will effectively be calling the `create` function over and over.

For example, let's create a user model and associate multiple location and email models to each one. Each email will also have multiple token models.

```
$user = $fm->create('User');
$profiles = $fm->seed(5, 'Location', ['user_id' => $user->id]);
$emails = $fm->seed(100, 'Email', ['user_id' => $user->id]);

foreach ($emails as $email) {
    $tokens = $fm->seed(50, 'Token', ['email_id' => $email->id]);
}
```

You may encounter the following exceptions:

- `League\FactoryMuffin\Exceptions\ModelNotFoundException` will be thrown if the model class defined is not found.
- `League\FactoryMuffin\Exceptions\DefinitionNotFoundException` will be thrown if you try to create a model and you haven't defined a model definition for it earlier.
- `League\FactoryMuffin\Exceptions\SaveFailedException` will be thrown if the save function on your model returns false.
- `League\FactoryMuffin\Exceptions\SaveMethodNotFoundException` will be thrown if the save function on your model does not exist.
- Any other exception thrown by your model while trying to create or save it.

There are 5 other helper functions available:

- You may call `pending` to return an array of all the objects waiting to be saved.
- You may call `isPending` with an instance of a model to check if will be saved.
- You may call `saved` to return an array of all the saved objects.
- You may call `isSaved` with an instance of a model to check if it's saved.
- You may call `isPendingOrSaved` with an instance of a model to check if it will be saved, or is already saved.

Also, a reminder that the `instance` function is still available if you don't want database persistence.

### Deleting

[](#deleting)

You can delete all your saved models with the `deleteSaved` function. Please note that your saved models will be deleted in the reverse order they were saved to ensure relationships behave correctly.

If one or more models cannot be deleted, a `League\FactoryMuffin\Exceptions\DeletingFailedException` will be raised after we have attempted to delete all the saved models. You may access each underlying exception, in the order they were thrown during the whole process, with the `getExceptions` function which will return an array of exceptions. You may encounter the following exceptions:

- `League\FactoryMuffin\Exceptions\DeleteFailedException` will be thrown if the delete function on your model returns false.
- `League\FactoryMuffin\Exceptions\DeleteMethodNotFoundException` will be thrown if the delete function on your model does not exist.
- Any other exception thrown by your model while trying to delete it.

It's recommended that you call the `deleteSaved` function from PHPUnit's `tearDownAfterClass` function, however, if you are writing tests using Laravel's `TestCase`, you should call the `deleteSaved` function from the `tearDown` method before calling `parent::tearDown`. This method flushes the application instance's bindings and Factory Muffin would not unable to execute its deletes. Further more, this unbinds the assigned exception handler and you will not be able to troubleshoot your tests due to binding resolution exceptions obfuscating the true exceptions.

### Real Examples

[](#real-examples)

To start with, we need to create some definitions:

```
# tests/factories/all.php

use League\FactoryMuffin\Faker\Facade as Faker;

$fm->define('Message')->setDefinitions([
    'user_id'      => 'factory|User',
    'subject'      => Faker::sentence(),
    'message'      => Faker::text(),
    'phone_number' => Faker::randomNumber(8),
    'created'      => Faker::date('Ymd h:s'),
    'slug'         => 'Message::makeSlug',
])->setCallback(function ($object, $saved) {
    // we're taking advantage of the callback functionality here
    $object->message .= '!';
});

$fm->define('User')->setDefinitions([
    'username' => Faker::firstNameMale(),
    'email'    => Faker::email(),
    'avatar'   => Faker::imageUrl(400, 600),
    'greeting' => 'RandomGreeting::get',
    'four'     => function() {
        return 2 + 2;
    },
]);
```

You can then use these factories in your tests:

```
# tests/TestUserModel.php

use League\FactoryMuffin\Faker\Facade as Faker;

class TestUserModel extends PHPUnit_Framework_TestCase
{
    protected static $fm;

    public static function setupBeforeClass()
    {
        // create a new factory muffin instance
        static::$fm = new FactoryMuffin();

        // you can customize the save/delete methods
        // new FactoryMuffin(new ModelStore('save', 'delete'));

        // load your model definitions
        static::$fm->loadFactories(__DIR__.'/factories');

        // you can optionally set the faker locale
        Faker::setLocale('en_EN');
    }

    public function testSampleFactory()
    {
        $message = static::$fm->create('Message');
        $this->assertInstanceOf('Message', $message);
        $this->assertInstanceOf('User', $message->user);
    }

    public static function tearDownAfterClass()
    {
        static::$fm->deleteSaved();
    }
}
```

### Further Information

[](#further-information)

If you want more information, the following resources are available to you:

- Generated api docs are available [here](http://factory-muffin.thephpleague.com/api/).
- [Philip Brown's](https://github.com/philipbrown) article is available [here](http://culttt.com/2013/05/27/laravel-4-fixture-replacement-with-factorymuff/).
- Our [test suite](tests) may also be useful to you.

Integrations
------------

[](#integrations)

- [CakePHP 3](https://github.com/gourmet/muffin)
- [Yii 2](https://github.com/saada/yii2-factory-muffin)

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

[](#contributing)

Please check out our [contribution guidelines](.github/CONTRIBUTING.md) for details.

Credits
-------

[](#credits)

Factory Muffin is based on [Zizaco Zizuini](https://github.com/Zizaco)'s original work on "Factory Muff", and is currently maintained by [Graham Campbell](https://github.com/GrahamCampbell). [Scott Robertson](https://github.com/scottrobertson) was also a co-maintainer before the 3.0 release. Thank you to all our wonderful [contributors](https://github.com/thephpleague/factory-muffin/contributors) too.

Security
--------

[](#security)

If you discover a security vulnerability within this package, please send an email to Graham Campbell at . All security vulnerabilities will be promptly addressed. You may view our full security policy [here](https://github.com/thephpleague/factory-muffin/security/policy).

License
-------

[](#license)

Factory Muffin is licensed under [The MIT License (MIT)](LICENSE).

For Enterprise
--------------

[](#for-enterprise)

Available as part of the Tidelift Subscription

The maintainers of `league/factory-muffin` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-league-factory-muffin?utm_source=packagist-league-factory-muffin&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

###  Health Score

53

—

FairBetter than 97% of packages

Maintenance19

Infrequent updates — may be unmaintained

Popularity68

Solid adoption and visibility

Community45

Growing community involvement

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 61.1% 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 ~87 days

Recently: every ~419 days

Total

34

Last Release

1982d ago

Major Versions

v1.6.4 → v2.0.0-RC12014-07-21

v2.1.1 → v3.0.0-beta12014-12-22

2.1.x-dev → v3.0.0-RC12015-07-20

PHP version history (3 changes)v1.0.0PHP &gt;=5.3.0

v2.0.0PHP &gt;=5.3.3

v3.0.0-beta1PHP &gt;=5.4.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/d95eb26cb8f3919bb5ca3b6d823daeabbf259663778a970349b245c580713c8e?d=identicon)[graham-campbell](/maintainers/graham-campbell)

![](https://avatars.githubusercontent.com/u/68361?v=4)[Scott Robertson](/maintainers/scottrobertson)[@scottrobertson](https://github.com/scottrobertson)

---

Top Contributors

[![GrahamCampbell](https://avatars.githubusercontent.com/u/2829600?v=4)](https://github.com/GrahamCampbell "GrahamCampbell (551 commits)")[![scottrobertson](https://avatars.githubusercontent.com/u/68361?v=4)](https://github.com/scottrobertson "scottrobertson (285 commits)")[![Zizaco](https://avatars.githubusercontent.com/u/777635?v=4)](https://github.com/Zizaco "Zizaco (31 commits)")[![pete-otaqui](https://avatars.githubusercontent.com/u/132719?v=4)](https://github.com/pete-otaqui "pete-otaqui (5 commits)")[![ls-michielrensen](https://avatars.githubusercontent.com/u/1837560?v=4)](https://github.com/ls-michielrensen "ls-michielrensen (3 commits)")[![dimrsilva](https://avatars.githubusercontent.com/u/382789?v=4)](https://github.com/dimrsilva "dimrsilva (3 commits)")[![jadb](https://avatars.githubusercontent.com/u/33527?v=4)](https://github.com/jadb "jadb (3 commits)")[![LostKobrakai](https://avatars.githubusercontent.com/u/2489835?v=4)](https://github.com/LostKobrakai "LostKobrakai (3 commits)")[![hexnet](https://avatars.githubusercontent.com/u/5594863?v=4)](https://github.com/hexnet "hexnet (2 commits)")[![JonoB](https://avatars.githubusercontent.com/u/627725?v=4)](https://github.com/JonoB "JonoB (1 commits)")[![jsyi](https://avatars.githubusercontent.com/u/2161327?v=4)](https://github.com/jsyi "jsyi (1 commits)")[![benharold](https://avatars.githubusercontent.com/u/997712?v=4)](https://github.com/benharold "benharold (1 commits)")[![alexpts](https://avatars.githubusercontent.com/u/1306916?v=4)](https://github.com/alexpts "alexpts (1 commits)")[![luiz-brandao](https://avatars.githubusercontent.com/u/704231?v=4)](https://github.com/luiz-brandao "luiz-brandao (1 commits)")[![MasonM](https://avatars.githubusercontent.com/u/651224?v=4)](https://github.com/MasonM "MasonM (1 commits)")[![mbicknese](https://avatars.githubusercontent.com/u/5147934?v=4)](https://github.com/mbicknese "mbicknese (1 commits)")[![outrunthewolf](https://avatars.githubusercontent.com/u/814246?v=4)](https://github.com/outrunthewolf "outrunthewolf (1 commits)")[![deancsmith](https://avatars.githubusercontent.com/u/387289?v=4)](https://github.com/deancsmith "deancsmith (1 commits)")[![philsturgeon](https://avatars.githubusercontent.com/u/67381?v=4)](https://github.com/philsturgeon "philsturgeon (1 commits)")[![pmccarren](https://avatars.githubusercontent.com/u/4959702?v=4)](https://github.com/pmccarren "pmccarren (1 commits)")

---

Tags

testingfactory

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[phpunit/phpunit

The PHP Unit Testing framework.

20.0k910.7M134.8k](/packages/phpunit-phpunit)[phpunit/php-code-coverage

Library that provides collection, processing, and rendering functionality for PHP code coverage information.

8.9k892.4M1.5k](/packages/phpunit-php-code-coverage)[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k497.0M23.6k](/packages/mockery-mockery)[behat/behat

Scenario-oriented BDD framework for PHP

4.0k96.8M2.0k](/packages/behat-behat)[symfony/phpunit-bridge

Provides utilities for PHPUnit, especially user deprecation notices management

2.5k201.2M4.2k](/packages/symfony-phpunit-bridge)[behat/mink

Browser controller/emulator abstraction for PHP

1.6k86.1M606](/packages/behat-mink)

PHPackages © 2026

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