{"id":20180559,"url":"https://github.com/ergebnis/factory-bot","last_synced_at":"2025-05-16T13:02:46.408Z","repository":{"id":37854892,"uuid":"245791628","full_name":"ergebnis/factory-bot","owner":"ergebnis","description":"🤖 Provides a composer package with a fixture factory for doctrine/orm entities.","archived":false,"fork":false,"pushed_at":"2025-04-21T17:19:43.000Z","size":5588,"stargazers_count":79,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-21T17:41:57.227Z","etag":null,"topics":["doctrine","entity","factory","fixture","orm"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ergebnis.png","metadata":{"funding":{"github":["ergebnis","localheinz"]},"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-08T10:10:08.000Z","updated_at":"2025-04-21T17:19:45.000Z","dependencies_parsed_at":"2023-10-26T17:31:07.021Z","dependency_job_id":"4d1bedff-40cf-4c3c-ac03-97bba8c425df","html_url":"https://github.com/ergebnis/factory-bot","commit_stats":{"total_commits":1407,"total_committers":7,"mean_commits":201.0,"dds":0.4108031272210376,"last_synced_commit":"f6fa5139450f753052b20080e44c426050d4546b"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":"ergebnis/php-package-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergebnis%2Ffactory-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergebnis%2Ffactory-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergebnis%2Ffactory-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ergebnis%2Ffactory-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ergebnis","download_url":"https://codeload.github.com/ergebnis/factory-bot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535792,"owners_count":22087397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["doctrine","entity","factory","fixture","orm"],"created_at":"2024-11-14T02:31:43.430Z","updated_at":"2025-05-16T13:02:46.352Z","avatar_url":"https://github.com/ergebnis.png","language":"PHP","funding_links":["https://github.com/sponsors/ergebnis","https://github.com/sponsors/localheinz"],"categories":[],"sub_categories":[],"readme":"# factory-bot\n\n[![Integrate](https://github.com/ergebnis/factory-bot/workflows/Integrate/badge.svg)](https://github.com/ergebnis/factory-bot/actions)\n[![Merge](https://github.com/ergebnis/factory-bot/workflows/Merge/badge.svg)](https://github.com/ergebnis/factory-bot/actions)\n[![Release](https://github.com/ergebnis/factory-bot/workflows/Release/badge.svg)](https://github.com/ergebnis/factory-bot/actions)\n[![Renew](https://github.com/ergebnis/factory-bot/workflows/Renew/badge.svg)](https://github.com/ergebnis/factory-bot/actions)\n\n[![Code Coverage](https://codecov.io/gh/ergebnis/factory-bot/branch/main/graph/badge.svg)](https://codecov.io/gh/ergebnis/factory-bot)\n\n[![Latest Stable Version](https://poser.pugx.org/ergebnis/factory-bot/v/stable)](https://packagist.org/packages/ergebnis/factory-bot)\n[![Total Downloads](https://poser.pugx.org/ergebnis/factory-bot/downloads)](https://packagist.org/packages/ergebnis/factory-bot)\n[![Monthly Downloads](http://poser.pugx.org/ergebnis/factory-bot/d/monthly)](https://packagist.org/packages/ergebnis/factory-bot)\n\nThis project provides a [`composer`](https://getcomposer.org) package with a fixture factory for [`doctrine/orm`](https://github.com/doctrine/orm) entities.\n\n## Installation\n\nRun\n\n```sh\ncomposer require --dev ergebnis/factory-bot\n```\n\n## Usage\n\nThe entry point of `ergebnis/factory-bot` is the [`FixtureFactory`](src/FixtureFactory.php).\n\nYou will use the fixture factory to create entity definitions and to create Doctrine entities populated with fake data.\n\n- [Examples](#examples)\n- [Creating a fixture factory](#creating-a-fixture-factory)\n- [Creating entity definitions](#creating-entity-definitions)\n- [Loading entity definitions](#loading-entity-definitions)\n- [Registering entity definitions](#registering-entity-definitions)\n- [Creating entities](#creating-entities)\n- [Persisting entities](#persisting-entities)\n- [Flushing entities](#flushing-entities)\n\n### Examples\n\nYou can find examples in\n\n- the directory [`example/`](example/)\n- the repository [`ergebnis/factory-bot-example`](https://github.com/ergebnis/factory-bot-example)\n\n### Creating a fixture factory\n\nThe fixture factory requires an instance of `Doctrine\\ORM\\EntityManagerInterface` (for reading class metadata from Doctrine entities, and for persisting Doctrine entities when necessary) and an instance of `Faker\\Generator` for generating fake data.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Doctrine\\ORM;\nuse Ergebnis\\FactoryBot;\nuse Faker\\Factory;\n\n$entityManager = ORM\\EntityManager::create(...);\n$faker = Factory::create(...);\n\n$fixtureFactory = new FactoryBot\\FixtureFactory(\n    $entityManager,\n    $faker\n);\n```\n\nTo simplify the creation of a fixture factory in tests, you can create an [abstract test case](example/test/Unit/AbstractTestCase.php) with access to an entity manager, a faker, and a fixture factory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Test\\Functional;\n\nuse Doctrine\\ORM;\nuse Ergebnis\\FactoryBot;\nuse Faker\\Generator;\nuse PHPUnit\\Framework;\n\nabstract class AbstractTestCase extends Framework\\TestCase\n{\n    final protected static function entityManager(): ORM\\EntityManagerInterface\n    {\n          // create entity manager from configuration or fetch it from container\n\n          return $entityManager;\n    }\n\n    final protected static function faker(): Generator\n    {\n        $faker = Factory::create();\n\n        $faker-\u003eseed(9001);\n\n        return $faker;\n    }\n\n    final protected static function fixtureFactory(): FactoryBot\\FixtureFactory\n    {\n        $fixtureFactory = new FactoryBot\\FixtureFactory(\n            static::entityManager(),\n            static::faker()\n        );\n\n        // create or load entity definitions\n\n        return $fixtureFactory;\n    }\n}\n```\n\n### Creating entity definitions\n\nNow that you have access to a fixture factory, you can create definitions for Doctrine entities.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class);\n```\n\nThis simple definition might work when all entity fields have default values, but typically, you will want to provide a map of entity field names to field definitions.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'avatar' =\u003e FactoryBot\\FieldDefinition::reference(Entity\\Avatar::class),\n    'id' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker): string {\n        return $faker-\u003euuid;\n    }),\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalClosure(static function (Generator $faker): string {\n        return $faker-\u003ecity;\n    }),\n    'login' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker): string {\n        return $faker-\u003euserName;\n    }),\n]);\n```\n\nIn addition to the map of field names to field definitions, you can specify a closure that the fixture factory will invoke after creating the entity. The closure accepts the freshly created entity and the map of field names to field values that the fixture factory used to populate the entity.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\n$closure = static function (object $entity, array $fieldValues): void {\n    // ...\n};\n```\n\n:bulb: You can use the closure to modify the freshly created entity.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(\n    Entity\\User::class,\n    [\n        'avatar' =\u003e FactoryBot\\FieldDefinition::reference(Entity\\Avatar::class),\n        'id' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker): string {\n            return $faker-\u003euuid;\n        }),\n        'location' =\u003e FactoryBot\\FieldDefinition::optionalClosure(static function (Generator $faker): string {\n            return $faker-\u003ecity;\n        }),\n        'login' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker): string {\n            return $faker-\u003euserName;\n        }),\n    ],\n    static function (Entity\\User $user, array $fieldValues): void {\n        if (is_string($fieldValues['location')) {\n            // ...\n        }\n    }\n);\n```\n\n#### Field Definitions\n\nA field definition can be\n\n- an implementation of [`FieldDefinition\\Resolvable`](src/FieldDefinition/Resolvable.php)\n- a closure (will be normalized to [`FieldDefinition\\Closure`](src/FieldDefinition/Closure.php))\n- an arbitrary value (will be normalized to [`FieldDefinition\\Value`](src/FieldDefinition/Value.php))\n\nYou can use the [`FieldDefinition`](src/FieldDefinition.php) factory to create field definitions shipped with this package or implement the `FieldDefinition\\Resolvable` interface yourself.\n\n:bulb: Custom field definitions can be useful when you are dealing with identical field definitions over and over again.\n\n#### Non-nullable fields\n\nWhen you are working with non-nullable fields, you can use the following field definitions, all of which will resolve to concrete references or values:\n\n- [`FieldDefinition::closure()`](#fielddefinitionclosure)\n- [`FieldDefinition::reference()`](#fielddefinitionreference)\n- [`FieldDefinition::references()`](#fielddefinitionreferences)\n- [`FieldDefinition::sequence()`](#fielddefinitionsequence)\n- [`FieldDefinition::value()`](#fielddefinitionvalue)\n\n#### Nullable fields\n\nWhen you are working with nullable fields, you can use the following field definitions, all of which will either resolve to `null` or to a concrete reference or value (depending on the [strategy](#creating-entities):\n\n- [`FieldDefinition::optionalClosure()`](#fielddefinitionoptionalclosure)\n- [`FieldDefinition::optionalReference()`](#fielddefinitionoptionalreference)\n- [`FieldDefinition::optionalSequence()`](#fielddefinitionoptionalsequence)\n- [`FieldDefinition::optionalValue()`](#fielddefinitionoptionalvalue)\n\n##### `FieldDefinition::closure()`\n\n`FieldDefinition::closure()` accepts a closure.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Faker\\Generator;\n\n$closure = static function (Generator $faker, FactoryBot\\FixtureFactory $fixtureFactory) {\n    // return whatever makes sense\n};\n```\n\nThe fixture factory will resolve the field definition to the return value of invoking the closure with the instance of `Faker\\Generator` composed into the fixture factory, and the fixture factory itself.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'id' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker): string {\n        return $faker-\u003euuid;\n    }),\n    'organizations' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker, FactoryBot\\FixtureFactory $fixtureFactory): array {\n        return $fixtureFactory-\u003ecreateMany(\n            Entity\\Organization::class,\n            FactoryBot\\Count::exact($faker-\u003enumberBetween(\n                1,\n                5\n            ))\n        );\n    }),\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003eid());            // string\nvar_dump($user-\u003eorganizations()); // array with 1-5 instances of Entity\\Organization\n```\n\n:bulb: It is possible to specify a closure only (will be normalized to `FieldDefinition\\Closure`):\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'id' =\u003e static function (Generator $faker): string {\n        return $faker-\u003euuid;\n    },\n    'organizations' =\u003e static function (Generator $faker, FactoryBot\\FixtureFactory $fixtureFactory): array {\n        return $fixtureFactory-\u003ecreateMany(\n            Entity\\Organization::class,\n            FactoryBot\\Count::exact($faker-\u003enumberBetween(\n                1,\n                5\n            ))\n        );\n    },\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003eid());            // string\nvar_dump($user-\u003eorganizations()); // array with 1-5 instances of Entity\\Organization\n```\n\n##### `FieldDefinition::optionalClosure()`\n\n`FieldDefinition::optionalClosure()` accepts a closure.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Faker\\Generator;\n\n$closure = static function (Generator $faker, FactoryBot\\FixtureFactory $fixtureFactory) {\n    // return whatever makes sense\n};\n```\n\nA fixture factory using the [`Strategy\\DefaultStrategy`](#strategydefaultstrategy) will resolve the field definition to `null` or to the return value of invoking the closure with the instance of `Faker\\Generator` composed into the fixture factory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalClosure(static function (Generator $faker): string {\n        return $faker-\u003ecity;\n    }),\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003elocation()); // null or a random city\n```\n\nA fixture factory using the [`Strategy\\WithOptionalStrategy`](#strategywithoptionalstrategy) will resolve the field definition to the return value of invoking the closure with the instance of `Faker\\Generator` composed into the fixture factory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalClosure(static function (Generator $faker): string {\n        return $faker-\u003ecity;\n    }),\n]);\n\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n\n/** @var Entity\\User $user */\n$user = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003elocation()); // a random city\n```\n\nA fixture factory using the [`Strategy\\WithoutOptionalStrategy`](#strategywithoutoptionalstrategy) will resolve the field definition to `null`.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalClosure(static function (Generator $faker): string {\n        return $faker-\u003ecity;\n    }),\n]);\n\n$withoutOptionalFixtureFactory = $fixtureFactory-\u003ewithoutOptional();\n\n/** @var Entity\\User $user */\n$user = $withoutOptionalFixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003elocation()); // null\n```\n\n##### `FieldDefinition::reference()`\n\n`FieldDefinition::reference()` accepts the class name of an entity or embeddable, and optionally an array of field definition overrides.\n\nEvery fixture factory will resolve the field definition to an instance of the entity or embeddable class populated through the fixture factory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'avatar' =\u003e FactoryBot\\FieldDefinition::reference(Entity\\Avatar::class),\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003eavatar()); // an instance of Entity\\Avatar\n```\n\nWhen field definition overrides are specified, they will be used to override exsting field definitions of the referenced entity.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'avatar' =\u003e FactoryBot\\FieldDefinition::reference(\n        Entity\\Avatar::class,\n        [\n            'height' =\u003e 300,\n            'width' =\u003e 200,\n        ]\n    ),\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003eavatar()); // an instance of Entity\\Avatar with height set to 300 and width set to 200\n```\n\n:exclamation: When resolving the reference, the fixture factory needs to be aware of the referenced entity or embeddable.\n\n##### `FieldDefinition::optionalReference()`\n\n`FieldDefinition::optionalReference()` accepts the class name of an entity or embeddable, and optionally an array of field definition overrides.\n\nA fixture factory using the [`Strategy\\DefaultStrategy`](#strategydefaultstrategy) will resolve the field definition to `null` or an instance of the entity or embeddable class populated through the fixture factory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\Repository::class, [\n    'template' =\u003e FactoryBot\\FieldDefinition::optionalReference(Entity\\Repository::class),\n]);\n\n/** @var Entity\\Repository $repository */\n$repository = $fixtureFactory-\u003ecreateOne(Entity\\Repository::class);\n\nvar_dump($repository-\u003etemplate()); // null or an instance of Entity\\Repository\n```\n\nA fixture factory using the [`Strategy\\WithOptionalStrategy`](#strategywithoptionalstrategy) will resolve the field definition to an instance of the entity or embeddable class populated through the fixture factory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\Repository::class, [\n    'template' =\u003e FactoryBot\\FieldDefinition::optionalReference(Entity\\Repository::class),\n]);\n\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n\n/** @var Entity\\Repository $repository */\n$repository = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\Repository::class);\n\nvar_dump($repository-\u003etemplate()); // an instance of Entity\\Repository\n```\n\nA fixture factory using the [`Strategy\\WithoutOptionalStrategy`](#strategywithoutoptionalstrategy) will resolve the field definition to `null`.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\Repository::class, [\n    'template' =\u003e FactoryBot\\FieldDefinition::optionalReference(Entity\\Repository::class),\n]);\n\n$withoutOptionalFixtureFactory = $fixtureFactory-\u003ewithoutOptional();\n\n/** @var Entity\\Repository $repository */\n$repository = $withoutOptionalFixtureFactory-\u003ecreateOne(Entity\\Repository::class);\n\nvar_dump($repository-\u003etemplate()); // null\n```\n\n:exclamation: When resolving the reference, the fixture factory needs to be aware of the referenced entity or embeddable.\n\n##### `FieldDefinition::references()`\n\n`FieldDefinition::references()` accepts the class name of an entity or embeddable, the count of desired references, and optionally an array of field definition overrides.\n\nYou can create the count from an exact number, or minimum and maximum values.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\n\n$count = FactoryBot\\Count::exact(5);\n\n$otherCount = FactoryBot\\Count::between(\n    0,\n    20\n);\n```\n\n:bulb: When you create the count from minimum and maximum values, the fixture factory will resolve its actual value before creating references. This way, you can have variation in the number of references - any number between the minimum and maximum can be assumed.\n\nA fixture factory using the [`Strategy\\DefaultStrategy`](#strategydefaultstrategy) will resolve the field definition to an array with zero or more instances of the entity or embeddable class populated through the fixture factory. Depending on the value of `$count`, the array might be empty.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\Organization::class, [\n    'members' =\u003e FactoryBot\\FieldDefinition::references(\n        Entity\\User::class,\n        FactoryBot\\Count::exact(5)\n    ),\n    'repositories' =\u003e FactoryBot\\FieldDefinition::references(\n        Entity\\Repository::class,\n        FactoryBot\\Count::between(0, 20),\n        [\n            'codeOfConduct' =\u003e null,\n        ]\n    ),\n]);\n\n/** @var Entity\\Organization $organization */\n$organization = $fixtureFactory-\u003ecreateOne(Entity\\Organization::class);\n\nvar_dump($organization-\u003emembers());      // array with 5 instances of Entity\\User\nvar_dump($organization-\u003erepositories()); // array with 0-20 instances of Entity\\Repository\n```\n\nA fixture factory using the [`Strategy\\WithOptionalStrategy`](#strategywithoptionalstrategy) will resolve the field definition to an array containing at least one instance of the entity or embeddable class populated through the fixture factory, unless `$count` uses an exact value, see [`FixtureFactory::createMany()`](#fixturefactorycreatemany).\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\Organization::class, [\n    'members' =\u003e FactoryBot\\FieldDefinition::references(\n        Entity\\User::class,\n        FactoryBot\\Count::exact(5)\n    ),\n    'repositories' =\u003e FactoryBot\\FieldDefinition::references(\n        Entity\\Repository::class,\n        FactoryBot\\Count::between(0, 20)\n    ),\n]);\n\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n\n/** @var Entity\\Organization $organization */\n$organization = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\Organization::class);\n\nvar_dump($organization-\u003emembers());      // array with 5 instances of Entity\\User\nvar_dump($organization-\u003erepositories()); // array with 1-20 instances of Entity\\Repository\n```\n\nA fixture factory using the [`Strategy\\WithoutOptionalStrategy`](#strategywithoutoptionalstrategy) will resolve the field definition to an empty array, unless `$count` uses an exact value, see [`FixtureFactory::createMany()`](#fixturefactorycreatemany).\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\Organization::class, [\n    'members' =\u003e FactoryBot\\FieldDefinition::references(\n        Entity\\User::class,\n        FactoryBot\\Count::exact(5)\n    ),\n    'repositories' =\u003e FactoryBot\\FieldDefinition::references(\n        Entity\\Repository::class,\n        FactoryBot\\Count::between(0, 20)\n    ),\n]);\n\n$withoutOptionalFixtureFactory = $fixtureFactory-\u003ewithoutOptional();\n\n/** @var Entity\\Organization $organization */\n$organization = $withoutOptionalFixtureFactory-\u003ecreateOne(Entity\\Organization::class);\n\nvar_dump($organization-\u003emembers());      // array with 5 instances of Entity\\User\nvar_dump($organization-\u003erepositories()); // empty array\n```\n\n:exclamation: When resolving the references, the fixture factory needs to be aware of the referenced entity or embeddable.\n\n##### `FieldDefinition::sequence()`\n\n`FieldDefinition::sequence()` accepts a string containing the `%d` placeholder at least once and an optional initial number (defaults to `1`).\n\nEvery fixture factory will resolve the field definition by replacing all occurrences of the placeholder `%d` in the string with the sequential number's current value. The sequential number will then be incremented by `1` for the next run.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'login' =\u003e FactoryBot\\FieldDefinition::sequence(\n        'user-%d',\n        1\n    ),\n]);\n\n/** @var Entity\\User $userOne */\n$userOne = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\n/** @var Entity\\User $userTwo */\n$userTwo = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($userOne-\u003elogin()); // 'user-1'\nvar_dump($userTwo-\u003elogin()); // 'user-2'\n```\n\n##### `FieldDefinition::optionalSequence()`\n\n`FieldDefinition::optionalSequence()` accepts a string containing the `%d` placeholder at least once and an optional initial number (defaults to `1`).\n\nA fixture factory using the [`Strategy\\DefaultStrategy`](#strategydefaultstrategy) will resolve the field definition to `null` or by replacing all occurrences of the placeholder `%d` in the string with the sequential number's current value. The sequential number will then be incremented by `1` for the next run.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalSequence(\n        'City %d',\n        1\n    ),\n]);\n\n/** @var Entity\\User $userOne */\n$userOne = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\n/** @var Entity\\User $userTwo */\n$userTwo = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($userOne-\u003elocation()); // null or 'City 1'\nvar_dump($userTwo-\u003elocation()); // null or 'City 1' or 'City 2'\n```\n\nA fixture factory using the [`Strategy\\WithOptionalStrategy`](#strategywithoptionalstrategy) will resolve the field definition by replacing all occurrences of the placeholder `%d` in the string with the sequential number's current value. The sequential number will then be incremented by `1` for the next run.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalSequence(\n        'City %d',\n        1\n    ),\n]);\n\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n\n/** @var Entity\\User $userOne */\n$userOne = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\User::class);\n\n/** @var Entity\\User $userTwo */\n$userTwo = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($userOne-\u003elocation()); // 'City 1'\nvar_dump($userTwo-\u003elocation()); // 'City 2'\n```\n\nA fixture factory using the [`Strategy\\WithoutOptionalStrategy`](#strategywithoutoptionalstrategy) will resolve the field definition to `null`.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalSequence(\n        'City %d',\n        1\n    ),\n]);\n\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n\n/** @var Entity\\User $userOne */\n$userOne = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\User::class);\n\n/** @var Entity\\User $userTwo */\n$userTwo = $withOptionalFixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($userOne-\u003elocation()); // null\nvar_dump($userTwo-\u003elocation()); // null\n```\n\n##### `FieldDefinition::value()`\n\n`FieldDefinition::value()` accepts an arbitrary value.\n\nThe fixture factory will resolve the field definition to the value.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'login' =\u003e FactoryBot\\FieldDefinition::value('localheinz'),\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003elogin()); // 'localheinz'\n```\n\n:bulb: It is also possible to specify a value only:\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'login' =\u003e 'localheinz',\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\nvar_dump($user-\u003elogin()); // 'localheinz'\n```\n\n##### `FieldDefinition::optionalValue()`\n\n`FieldDefinition::optionalValue()` accepts an arbitrary value.\n\nA fixture factory using the [`Strategy\\DefaultStrategy`](#strategydefaultstrategy) will resolve the field definition to `null` or the value.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalValue('Berlin'),\n]);\n\n/** @var Entity\\User $user */\n$user = $fixtureFactory-\u003ecreate(Entity\\User::class);\n\nvar_dump($user-\u003elocation()); // null or 'Berlin'\n```\n\nA fixture factory using the [`Strategy\\WithOptionalStrategy`](#strategywithoptionalstrategy) will resolve the field definition to the value.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalValue('Berlin'),\n]);\n\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n\n/** @var Entity\\User $user */\n$user = $withOptionalFixtureFactory-\u003ecreate(Entity\\User::class);\n\nvar_dump($user-\u003elocation()); // 'Berlin'\n```\n\nA fixture factory using the [`Strategy\\WithoutOptionalStrategy`](#strategywithoutoptionalstrategy) will resolve the field definition to `null`.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'location' =\u003e FactoryBot\\FieldDefinition::optionalValue('Berlin'),\n]);\n\n$withoutOptionalFixtureFactory = $fixtureFactory-\u003ewithoutOptional();\n\n/** @var Entity\\User $user */\n$user = $withoutOptionalFixtureFactory-\u003ecreate(Entity\\User::class);\n\nvar_dump($user-\u003elocation()); // null\n```\n\n### Loading entity definitions\n\nInstead of creating entity definitions inline, you can implement the [`EntityDefinitionProvider`](src/EntityDefinitionProvider.php) interface and load entity definitions contained within a directory with the fixture factory.\n\nFirst, create concrete definition providers.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nnamespace Example\\Test\\Fixture\\Entity;\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\n\nfinal class UserDefinitionProvider implements FactoryBot\\EntityDefinitionProvider\n{\n    public function accept(FactoryBot\\FixtureFactory $fixtureFactory): void\n    {\n        $fixtureFactory-\u003edefine(Entity\\User::class, [\n            // ...\n        ]);\n    }\n}\n```\n\n:bulb: While you can use a single entity definition provider to provide definitions for all entities, I recommend using one definition provider per entity. Then you can quickly implement an [auto-review test](example/test/AutoReview/FixtureTest.php) to enforce that an entity definition provider exists for each entity.\n\nSecond, adjust your abstract test case to load definitions from entity definition providers contained in a directory.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Test\\Functional;\n\nuse Ergebnis\\FactoryBot;\nuse PHPUnit\\Framework;\n\nabstract class AbstractTestCase extends Framework\\TestCase\n{\n    // ...\n\n    final protected static function fixtureFactory(): FactoryBot\\FixtureFactory\n    {\n        $fixtureFactory = new FactoryBot\\FixtureFactory(\n            static::entityManager(),\n            static::faker()\n        );\n\n        $fixtureFactory-\u003eload(__DIR__ . '/../Fixture');\n\n        return $fixtureFactory;\n    }\n\n    // ...\n}\n```\n\n### Registering entity definitions\n\nInstead of loading entity definition providers contained within a directory with the fixture factory, you can also register entity definition providers that you have already instantiated.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Test\\Functional;\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Test\\Fixture;\nuse PHPUnit\\Framework;\n\nabstract class AbstractTestCase extends Framework\\TestCase\n{\n    // ...\n\n    final protected static function fixtureFactory(): FactoryBot\\FixtureFactory\n    {\n        $fixtureFactory = new FactoryBot\\FixtureFactory(\n            static::entityManager(),\n            static::faker()\n        );\n\n        $fixtureFactory-\u003eregister(new Fixture\\UserDefinitionProvider());\n\n        return $fixtureFactory;\n    }\n\n    // ...\n}\n```\n\n### Creating entities\n\nNow that you have created (or loaded) entity definitions, you can create Doctrine entities populated with fake data.\n\nThe fixture factory allows to create entities using the following strategies:\n\n[`Strategy\\DefaultStrategy`](#strategydefaultstrategy)\n[`Strategy\\WithOptionalStrategy`](#strategywithoptionalstrategy)\n[`Strategy\\WithoutOptionalStrategy`](#strategywithoutoptionalstrategy)\n\n#### `Strategy\\DefaultStrategy`\n\nThe `Strategy\\DefaultStrategy` involves random behavior, and based on randomness, the fixture factory might or might not resolve optional field references:\n\n- [`FieldDefinition::optionalClosure()`](#fielddefinitionoptionalclosure) might be resolved to `null` or a concrete value\n- [`FieldDefinition::optionalReference()`](#fielddefinitionoptionalreference) might be resolved to `null` or a concrete reference\n- [`FieldDefinition::optionalSequence()`](#fielddefinitionoptionalsequence) might be resolved to `null` or a concrete value\n- [`FieldDefinition::optionalValue()`](#fielddefinitionoptionalvalue) might be resolved to `null` or a concrete value\n- [`FieldDefinition::references()`](#fielddefinitionreferences) might be resolved to an `array` of zero or more references\n\nThe fixture factory uses the `Strategy\\DefaultStrategy` by default.\n\n#### `Strategy\\WithOptionalStrategy`\n\nThe `Strategy\\WithOptionalStrategy` involves random behavior, but the fixture factory will resolve optional field references:\n\n- [`FieldDefinition::optionalClosure()`](#fielddefinitionoptionalclosure) will be resolved to a concrete value\n- [`FieldDefinition::optionalReference()`](#fielddefinitionoptionalreference) will be resolved to a concrete reference\n- [`FieldDefinition::optionalSequence()`](#fielddefinitionoptionalsequence) will be resolved to a concrete value\n- [`FieldDefinition::optionalValue()`](#fielddefinitionoptionalvalue) will be resolved to a concrete value\n- [`FieldDefinition::references()`](#fielddefinitionreferences) will be resolved to an `array` containing at least one reference, unless `$count` uses an exact value, see [`FixtureFactory::createMany()`](#fixturefactorycreatemany)\n\nTo create a fixture factory using the `Strategy\\WithOptionalStrategy` out of an available fixture factory, invoke `withOptional()`:\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$withOptionalFixtureFactory = $fixtureFactory-\u003ewithOptional();\n```\n\n#### `Strategy\\WithoutOptionalStrategy`\n\nThe `Strategy\\WithoutOptionalStrategy` involves random behavior, but the fixture factory will not resolve optional field references:\n\n- [`FieldDefinition::optionalClosure()`](#fielddefinitionoptionalclosure) will be resolved to `null`\n- [`FieldDefinition::optionalReference()`](#fielddefinitionoptionalreference) will be resolved to `null`\n- [`FieldDefinition::optionalSequence()`](#fielddefinitionoptionalsequence) will be resolved to `null`\n- [`FieldDefinition::optionalValue()`](#fielddefinitionoptionalvalue) will be resolved to `null`\n- [`FieldDefinition::references()`](#fielddefinitionreferences) will be resolved to an empty `array`, unless `$count` uses an exact value, see [`FixtureFactory::createMany()`](#fixturefactorycreatemany)\n\nTo create a fixture factory using the `Strategy\\WithoutOptionalStrategy` out of an available fixture factory, invoke `withoutOptional()`:\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$withoutOptionalFixtureFactory = $fixtureFactory-\u003ewithoutOptional();\n```\n\n#### `FixtureFactory::createOne()`\n\n`FixtureFactory::createOne()` accepts the class name of an entity and optionally, a map of entity field names to field definitions that should override the field definitions for that specific entity.\n\nThe fixture factory will return a single entity.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'login' =\u003e FactoryBot\\FieldDefinition::closure(static function (Generator $faker): string {\n        return $faker-\u003euserName;\n    }),\n]);\n\n/** @var Entity\\User $userOne */\n$userOne = $fixtureFactory-\u003ecreateOne(Entity\\User::class);\n\n/** @var Entity\\User $userTwo */\n$userTwo = $fixtureFactory-\u003ecreateOne(Entity\\User::class, [\n    'login' =\u003e FactoryBot\\FieldDefinition::value('localheinz'),\n]);\n\n/** @var Entity\\User $userThree */\n$userThree = $fixtureFactory-\u003ecreateOne(Entity\\User::class, [\n    'login' =\u003e 'ergebnis-bot',\n]);\n\nvar_dump($userOne-\u003elogin());   // random user name\nvar_dump($userTwo-\u003elogin());   // 'localheinz'\nvar_dump($userThree-\u003elogin()); // 'ergebnis-bot'\n```\n\nA field definition override can be\n\n- an implementation of [`FieldDefinition\\Resolvable`](src/FieldDefinition/Resolvable.php)\n- a closure (will be normalized to `FieldDefinition\\Closure`)\n- an arbitrary value (will be normalized to `FieldDefinition\\Value`)\n\nAlso see [Creating entity definitions](#creating-entity-definitions).\n\n#### `FixtureFactory::createMany()`\n\n`FixtureFactory::createMany()` accepts the class name of an entity, the count of desired entities, and an optional map of entity field names to field definitions that should override the field definitions for that specific entity.\n\nYou can create the count from an exact number:\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\n\n$count = FactoryBot\\Count::exact(5);\n```\n\nThe fixture factory will resolve `$count` to `5`.\n\nYou can also create the count from minimum and maximum values.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\n\n$count = FactoryBot\\Count::between(\n    0,\n    20\n);\n```\n\nThe fixture factory will resolve `$count` to any number between `0` and `20`.\n\nThe fixture factory will return an array of entities.\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\nuse Example\\Entity;\nuse Faker\\Generator;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$fixtureFactory-\u003edefine(Entity\\User::class, [\n    'login' =\u003e FieldDefinition\\Closure(static function (Generator $faker): string {\n        return $faker-\u003eusername;\n    }),\n]);\n\n/** @var array\u003cEntity\\User\u003e $users */\n$users = $fixtureFactory-\u003ecreateMany(\n    Entity\\User::class,\n    FactoryBot\\Count::exact(5)\n);\n\n/** @var array\u003cEntity\\User\u003e $otherUsers */\n$otherUsers = $fixtureFactory-\u003ecreateMany(\n    Entity\\User::class,\n    FactoryBot\\Count::exact(5),\n    [\n        'login' =\u003e FactoryBot\\FieldDefinition::sequence('user-%d'),\n    ]\n);\n\n$normalize = static function (array $users): array {\n    return array_map(static function (Entity\\User $user): string {\n        return $user-\u003elogin();\n    }, $users);\n};\n\nvar_dump($normalize($users));        // random user names\nvar_dump($normalize($otherUsers));   // 'user-1', 'user-2', ...\n```\n\nA field definition override can be\n\n- an implementation of [`FieldDefinition\\Resolvable`](src/FieldDefinition/Resolvable.php)\n- a closure (will be normalized to `FieldDefinition\\Closure`)\n- an arbitrary value (will be normalized to `FieldDefinition\\Value`)\n\nAlso see [Creating entity definitions](#creating-entity-definitions).\n\n### Persisting entities\n\nWhen the fixture factory creates entities, the fixture factory does not persist them by default.\n\nTo create a fixture factory that persists entities out of an available fixture factory, invoke `persisting()`:\n\n```php\n\u003c?php\n\ndeclare(strict_types=1);\n\nuse Ergebnis\\FactoryBot;\n\n/** @var FactoryBot\\FixtureFactory $fixtureFactory */\n$persistingFixtureFactory = $fixtureFactory-\u003epersisting();\n```\n\nAfter this point, the fixture factory will automatically persist every entity it creates.\n\n:exclamation: You need to flush the entity manager yourself.\n\n### Flushing entities\n\nThe fixture factory will not flush the entity manager - you need to flush it yourself.\n\n## Changelog\n\nThe maintainers of this project record notable changes to this project in a [changelog](CHANGELOG.md).\n\n## Contributing\n\nThe maintainers of this project suggest following the [contribution guide](.github/CONTRIBUTING.md).\n\n## Code of Conduct\n\nThe maintainers of this project ask contributors to follow the [code of conduct](https://github.com/ergebnis/.github/blob/main/CODE_OF_CONDUCT.md).\n\n## General Support Policy\n\nThe maintainers of this project provide limited support.\n\nYou can support the maintenance of this project by [sponsoring @localheinz](https://github.com/sponsors/localheinz) or [requesting an invoice for services related to this project](mailto:am@localheinz.com?subject=ergebnis/factory-bot:%20Requesting%20invoice%20for%20services).\n\n## PHP Version Support Policy\n\nThis project supports PHP versions with [active and security support](https://www.php.net/supported-versions.php).\n\nThe maintainers of this project add support for a PHP version following its initial release and drop support for a PHP version when it has reached the end of security support.\n\n## Security Policy\n\nThis project has a [security policy](.github/SECURITY.md).\n\n## License\n\nThis project uses the [MIT license](LICENSE.md).\n\n## Credits\n\nThis project is based on [`breerly/factory-girl-php@0e6f1b6`](https://github.com/GoodPete/factory-girl-php/tree/0e6f1b6724d39108a2e7cef68a74668b7a77b856) (originally licensed under MIT by [Grayson Koonce](https://github.com/unhashable)), which is based on [`xi/doctrine`](https://github.com/xi-project/xi-doctrine) (originally licensed under MIT by [Xi](https://github.com/xi-project)), which in turn provided a port of [`factory_bot`](https://github.com/thoughtbot/factory_girl) (originally licensed under MIT by [Joe Ferris](https://github.com/jferris) and [thoughtbot, Inc.](https://github.com/thoughtbot)).\n\n## Social\n\nFollow [@localheinz](https://twitter.com/intent/follow?screen_name=localheinz) and [@ergebnis](https://twitter.com/intent/follow?screen_name=ergebnis) on Twitter.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fergebnis%2Ffactory-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fergebnis%2Ffactory-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fergebnis%2Ffactory-bot/lists"}