zenstruck/foundry
Expressive, autocompletable fixture factories for Symfony + Doctrine (ORM and/or MongoDB). Create random-but-valid entities on demand for fixtures and tests, with states, persistence helpers, and rich testing features via ZenstruckFoundryBundle.
9ab871f feat: load multiple groups/stories with foundry:load-fixtures (#1138) by @podoko
2624ee7 fix: prevent flushes from corrupting tracked objects reset as lazy ghosts (ORM 2 / ODM without native lazy objects). (#1147) by @nikophil f26a1c7 minor: re-enable BC check by stripping the Behat subpackage from compared revisions (#1150) by @nikophil, @claude c4dd64a fix(behat): fix package split workflow by @nikophil
eaabcd1 minor: remove clone in autorefresh() and fix stale tracked objects with ORM 2 (#1146) by @nikophil, @claude
0b0f065 minor: reuse PersistenceManager::reattach() and clean up refresh()/autorefresh() (#1144) by @nikophil, @claude
02c1b66 fix(ci): explicitly set matrix defaults in include entries (#1143) by @nikophil, @claude
81abe19 fix: global state should always be reatached in Doctrine (#1142) by @nikophil
c256db4 fix: global state should not be accessed when persistence is not available (#1141) by @nikophil
bc4c489 fix: introduce PersistenceManager::reattach() (#1140) by @nikophil
ec03220 feat(behat): follow foundry tags and mark the integration as experimental (#1137) by @nikophil
b69cde4 feat(behat): fix composer dependencies by @nikophil
24c00f7 minor(behat): bump foundry ^2.11 by @nikophil
3a13443 feat(behat): --lowest run should use doctrine/orm ^2 (#1136) by @nikophil
ece8617 feat(behat): use specific PAT for split by @nikophil
9d36994 fix(behat): split subtree needs correct PAT by @nikophil
7ae1e71 fix(behat): make symlink-vendor.sh a no-op outside the monorepo (#1085) by @nikophil
06a514a chore(behat): exclude dev-only files from the split package dist (#1085) by @nikophil
1681d55 chore(behat): untrack composer.lock, already gitignored (#1085) by @nikophil
b307efe ci(behat): trigger the Behat workflow on main-package changes (#1085) by @nikophil
b20d8b2 test(behat): specify @withFixture semantics in disabled reset mode (#1085) by @nikophil
bff4466 test(behat): exercise every wording variant of the property assertion steps (#1085) by @nikophil
6c43019 test(behat): fix contradictory scenario title in disabled-mode feature (#1085) by @nikophil
8337ae9 test(behat): turn three registry has() calls into real assertions (#1085) by @nikophil
f0cf153 test(behat): cover the FoundryExtension configuration validation matrix (#1085) by @nikophil
69e67e0 fix(behat): drop @internal from the documented injection points (#1085) by @nikophil
0d754d0 docs: document the shared-container contract of BehatServicesCompilerPass (#1085) by @nikophil
252719d fix(behat): replace the Configuration booted by the bundle at exercise start (#1085) by @nikophil
8b7f771 fix(behat): do not reload global stories under DAMA's native extension (#1085) by @nikophil
4dd59ac fix(behat): reset the database at suite start in manual mode with DAMA support (#1085) by @nikophil
00feb6a fix(behat): fail loudly when DAMA support is enabled without the bundle (#1085) by @nikophil
91fd887 fix(behat): support quoted names in object()/lastObject() placeholders (#1085) by @nikophil
5c71353 fix(behat): register falsy object names like "0" at creation (#1085) by @nikophil
2fb1775 fix(behat): allow Background blocks to re-register named objects across scenarios (#1085) by @nikophil
b84c9ce fix(behat): resolve the identifier field name for lastId/lastObject placeholders (#1085) by @nikophil
42a234f fix(behat): normalize object identifiers in assertSameObject comparisons (#1085) by @nikophil
3df8b3f fix: only store in ObjectRegistry when actually running Behat (#1085) by @nikophil
6446224 feat(behat): replace step translations with trait-based context composition (#1085) by @nikophil
1725b6a feat(behat): prefix Behat transformers with "foundry:" (#1085) by @nikophil
dacf86a feat: database-backed id placeholders and assertion steps (#1085) by @nikophil
b24a1a9 fix: few fixes after agentic review (#1085) by @nikophil
0e11dd8 feat: override steps using translation (#1085) by @nikophil
800abc4 docs: clarify ref(type, name) syntax as an escape hatch (#1085) by @nikophil, @claude
f33dbcf feat: support UUID-based entity ids in ObjectRegistry (#1085) by @nikophil, @claude
c312ab9 fix: allow quoted object names starting with digits in regex patterns (#1085) by @nikophil, @claude
d46d219 fix: improve error messages in AbstractFoundryContext (#1085) by @nikophil, @claude
f609e65 perf: optimize class-to-factory lookups with index map in FactoryShortNameResolver (#1085) by @nikophil, @claude
8fef5a0 refactor: extract table normalization into private methods in FoundryCallFilter (#1085) by @nikophil, @claude
743eaf5 chore: zenstruck/foundry-behat a subpackage (#1084) (#1085) by @nikophil
8776ae9 feat/behat context (#1083) (#1085) by @nikophil
PrePersist listeners is no longer visible from hooks with default priorityPreviously, objects created by nested factories were passed to $em->persist() during the
creation of the object graph. Their PrePersist listeners could therefore observe — and even
corrupt (#1115) — a half-built graph, but it also meant their side effects (e.g. a field computed
in the listener) were already applied when your afterInstantiate() hooks ran.
Persistence is now deferred until the whole object graph is instantiated and wired, so hooks with
default priority run before any lifecycle event has been triggered. If one of your hooks reads
state computed by a PrePersist listener, give it a priority lower than
PersistentObjectFactory::PRIORITY_SCHEDULE_FOR_INSERT:
use Zenstruck\Foundry\Persistence\PersistentObjectFactory;
OrderItemFactory::new()
->afterInstantiate(function(OrderItem $item): void {
// computed in Order's PrePersist listener — visible here, on a fully wired graph
$item->setProcess($item->getOrder()->getProcess());
}, priority: PersistentObjectFactory::PRIORITY_SCHEDULE_FOR_INSERT - 1);
c851f6d fix: defer `$em->persist()` until the object graph is wired + natural accessor directionality (#1134) by [@nikophil](https://github.com/nikophil)
[Full Change List](https://github.com/zenstruck/foundry/compare/v2.10.2...v2.10.3)
1ad45ac fix: withoutDoctrineEvents() should not remove loadClassMetadata listeners (#1133) by @nikophil
5553b63 fix: withoutDoctrineEvents should work with nested entities (#1132) by @nikophil
6917146 chore: fix Roave BC check (composer >= 2.9.8) and restrict phpunit < 13.2 (#1127) by @nikophil
d9ed62b doc: add README Security Policy section (#1123) by @Copilot
bc10d82 fix: withoutDoctrineEvents should do nothgin in unit tests (#1121) by @VincentLanglet
db2b673 fix: use full semver versions for PHPUnit requirements (#1118) by @nikophil
d109883 Update warning message for Foundry v2 documentation (#1113) by @gisostallenberg
31c90dd Minor doc fix (#1117) by @javiereguiluz
11f55e7 feat: throw when withoutDoctrineEvents() is called within flush_after() (#1111) by @nikophil
f81db0d feat: add withoutDoctrineEvents() to suppress listeners during factory create (#1109) by @seb-jean
1408436 fix: factory template formatting (#1110) by @enekochan
b8f8909 minor: change Foundry's baseline (#1108) by @nikophil
5e70129 fix: arrange compatibility with PHPUnit 10 (#1103) by @nikophil
47a431c chore(ci): use-dama => no-dama (#1090) by @nikophil d8ce94b fix: ensure in WebTestCase with kernel already boot does not occur (#1088) by @nikophil 4820f3c chore: fix bug report template by @nikophil 516b786 chore: test using PHPunit 13 (#1086) by @nikophil 692f74c docs: minor docs fixes (#1082) by @nikophil
This release deprecates Factories and ResetDatabase traits in favor of the usage of the PHPUnit extension shipped with Foundry. These features mainly impact users using PHPUnit >= 10.
You can now remove all usages of the Factories trait. And replace the trait ResetDatabase with the attribute #[ResetDatabase]. Rectors sets are shipped with the release, see https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.9.md.
You can even automate the reset database mechanism:
<!-- phpunit.xml -->
<phpunit>
<extensions>
<bootstrap class="Zenstruck\Foundry\PHPUnit\FoundryExtension">
<parameter name="enabled-auto-reset" value="true"/>
</bootstrap>
</extensions>
</phpunit>
This will automatically reset the database before all KernelTestCase tests. With this configuration, even #[ResetDatabase] traits can be omitted.
5e11589 minor: fix last bits before release (#1080) by @nikophil
4f97e89 fix(in-memory): trigger in memory on PreparationStarted (#1077) (#1080) by @nikophil
e539491 fix: handle reset DB mechanism along with "before hooks" methods (#1070) (#1080) by @nikophil
2d59700 feat: automatic DB reset (#1068) (#1080) by @nikophil
9aaf683 minor: remove useless Factories trait (#1067) (#1080) by @nikophil
78b95d1 feat(2.9): deprecate ResetDatabase trait (#985) (#1080) by @nikophil
11b4b03 fix permutations in .github/workflows/phpunit.yml (#1080) by @nikophil
3025311 remove useless import (#1080) by @nikophil
f91c2fa fix: fixes after deprecating Factories trait (#1066) (#1080) by @nikophil
deb7637 feat(2.9): deprecate Factories trait and force PHPUnit extension usage (#968) (#1080) by @nikophil
e57d750 refactor: harmonize how factories are proxified in data providers (#1065) (#1080) by @nikophil
9cbf3c7 minor: some house keeping (#1064) (#1080) by @nikophil
c45e03c fix: allow deleting ghost object (#1076) by @nikophil 86a2036 minor: provide a way to skip faker's seed management (#1075) by @nikophil 32542a6 chore: use APP_ENV=test for benchmark (#1074) by @nikophil 4b6324e minor: add priorities for PHPUnit hooks (#1073) by @nikophil 63c3cac minor: use test environment (#1072) by @nikophil 5dccced Update issue templates (#1064) by @nikophil
f6e35e5 fix(autorefresh): prevent weird autorefresh recursion (#1060) by @nikophil 377c6d4 fix: handle derived entities in autorefresh mechanism (#1058) by @nikophil 8701b45 mnior: reboot kernel in database resetter instead of shutdown (#1059) by @nikophil 965fe3c refactor: simplify ResetDatabaseManager (#1054) by @nikophil 473559c chore: add PHP 8.5 to test matrix (#1043) by @nikophil 6c3a127 refactor: explicitly boot Foundry in ResetDatabase (#1049) by @nikophil 368e686 chore: skip legacy proxy tests using #[RequiresMethod] (#1048) by @nikophil d7add25 chore: require symfony/flex as dev dependency (#1047) by @nikophil
45b6e21 fix: remove problematic "conflict" in composer.json (#1046) by @nikophil
a102c0a fix: Allow PersistManager::refresh() to not throw in specific cases (#1044) by @nikophil d4f9997 fix: auto-refresh problem with doctrine/orm 2 (#1042) by @nikophil cace455 Update issue templates by @nikophil b0a5703 fix: call inverse relatoinship callback before afterInstantiate() (#1041) by @nikophil
9621dae Improve phpdoc for non empty list (#1037) by @VincentLanglet
7b9dc07 chore: actually suport Symfony 8 (#1022) by @nikophil
This release introduces a new attribute #[AsFoundryHook], which allows to declare Foundry hooks as Symfony services. It also permits to have "global" hooks for all kind of objects created with Foundry:
final class FoundryHook
{
#[AsFoundryHook(Post::class)]
public function beforeInstantiate(BeforeInstantiate $event): void
{
// do something before the post is instantiated:
// $event->parameters is what will be used to instantiate the object, manipulate as required
// $event->objectClass is the class of the object being instantiated
// $event->factory is the factory instance which creates the object
}
#[AsFoundryHook(Post::class)]
public function afterInstantiate(AfterInstantiate $event): void
{
// $event->object is the instantiated Post object
// $event->parameters contains the attributes used to instantiate the object and any extras
// $event->factory is the factory instance which creates the object
}
#[AsFoundryHook(Post::class)]
public function afterPersist(AfterPersist $event): void
{
// this event is only called if the object was persisted
// $event->object is the persisted Post object
// $event->parameters contains the attributes used to instantiate the object and any extras
// $event->factory is the factory instance which creates the object
}
#[AsFoundryHook]
public function afterInstantiateGlobal(AfterInstantiate $event): void
{
// Omitting the class defines a "global" hook which will be called for all objects
}
}
8dc0b1f feat(2.8): introduce #[AsFoundryHook] attribute (#986) by @nikophil
bf4549c feat(2.8): dispatch events (#974) by @nikophil
8516af1 docs: Remove array params on function alwaysForce (#1028) by @philpichet
5f3a6b1 feat: add hooks priority (#1029) by @nikophil
41ab3ae fix: auto-refresh with Mongo after DoctrineMongoDBBundle 5.4.3 (#1030) by @nikophil
728c8f8 minor: Add default value to Factory::attributes (#1026) by @VincentLanglet 0fe1017 tests: ensure Doctrine lifecycle works (#1020) by @nikophil 1247b0b chore: remove paratest from dev dependencies (#1023) by @nikophil 11355a9 chore: add concurrency for all workflows (#1019) by @nikophil fed6e4a chore: fix rector with bamarni (#1018) by @nikophil 545cf18 chore: split CIs and add concurrency (#1017) by @nikophil 17796f2 chore: add bc-check to CI (#1016) by @nikophil b8ced9b chore: disable sync template for cs config (#1015) by @nikophil b802463 chore: some housekeeping (#1014) by @nikophil
7766a85 fix: only use PersistedObjectsTracker when auto-refresh is enabled (#1013) by @nikophil
95d2a96 fix: autorefresh should work after kernel shutdown (#1011) by @nikophil 0ea8430 tests: ensure OneToMany relationships are refreshed (#1010) by @nikophil 3c6faff fix: RepositoryAssertion::exist() $criteria should allow mixed (#1007) by @nikophil 81cc97d minor: accept as story any child of Story (#1006) by @alsciende e99f3b0 chore: run rector CI with PHPUnit 12 (#1002) by @nikophil
81eacf5 docs: add a note about using make:factory --test (#1000) by @ttskch
660942d [Rector] Add rector to require-dev and use single autoload vendor for run PHPUnit (#1001) by @samsonasik
f06d58d fix: using refresh_all() with flush_after() (#999) by @HypeMC
9489e83 fix: 🐛 use isser instead of constructor to apply autorefresh setting to Factory (#998) by @ttskch
45214f7 fix: revert adding PersistManager::findBy() (#996) by @nikophil b36b9b3 chore: upgrade PHPStan (#997) by @nikophil 55f2689 fix: edge case with Doctrine Middleware & early kernel boot (#993) by @HypeMC 9fa21b3 fix(repository): use IN() when an array is passed (#995) by @nikophil cad1466 fix: handle readonly when refreshing from repository decorator (#989) by @nikophil b4b2ffe fix: Enhanced random method with additional safety check. (#991) by @sofwar
97b60b6 fix: applyStateMethod should not be internal (#988) by @nikophil
This release deprecates the proxy system in PHP 8.4 in favor of an auto-refresh mechanism which leverages PHP lazy objects.
Please follow the upgrade guide.
cd1b31a docs: add "Troubleshooting" section in upgrade guide (#943) by @nikophil a83c249 feat: enable auto-refresh at factory level (#970) by @nikophil 32e9868 fix: few fixes after #972 (#943) by @nikophil 47b0d79 feat: use ghost objects for auto refresh mechanism (#967) (#943) by @nikophil 3a131ef minor: improve deprecation message (#943) by @nikophil 30df79d feat: auto-refresh objects from RepositoryDecorator (#943) by @nikophil f675c37 minor: use ProxyGenerator::unwrap() instead of unproxy() and prevent deprec (#943) by @nikophil 9d04094 minor: remove PersistedObjectsTracker::reset() call in tear down (#943) by @nikophil 3e23fda refactor(maker): deprecate --with-phpdocs for PHP >=8.4 (#952) (#943) by @nikophil 61cabac docs: create upgrade guide to 2.7 and document auto-refresh (#951) (#943) by @nikophil fe6374b feat: auto refresh with lazy object php84 enabled by config (#950) (#943) by @nikophil 9717676 feat: Rector rules to help migrating away from proxy (#941) (#943) by @nikophil 35e8da6 feat: use native proxies for object creation in data providers (#943) by @nikophil 02f85f2 feat: create proxy system with PHP 8.4 lazy proxies (#943) by @nikophil
67a7731 fix: misc fixes when creating objects in data provider (#972) by @nikophil 5e068c4 fix: ignore PHPUnit warnings when dataprovider returns more data than test method accepts (#958) by @nikophil 0a65872 Fix proxying of classes that have tenative return types (#962) by @BackEndTea f9e95cb fix: doctrine deprecation (#961) by @nikophil c8256e3 Add support for Symfony 8 (#960) by @Kocal
6f4e920 fix(proxy): add autorefresh call for union and intersection return types (#959) by @BackEndTea 58fd89a feat: introduce method FactoryCollection::applyStateMethod() (#956) by @nikophil
932c63a feat: rename foundry:load-stories to foundry:load-fixtures (#954) by @kbond
1d31275 Update index.rst (#945) by @treztreiz
e5e5162 fix: doctrine deprecation (#949) by @nikophil
dc54221 Update index.rst (#946) by @treztreiz
5ae21ec docs: fix forceSet() to _set() in example (#948) by @mariecharles, Marie CHARLES
56161cc feat: add randomRangeOrCreate() method (#932) by @elliotbruneel, Elliot Bruneel
2d28e67 test: ensure no deprecation when Factories used in parent class (#922) by @nikophil
b25eb60 minor: fix running phpunit w/o arguments (#933) by @kbond
f9b8132 minor: add UID types to factory maker (#936) by @HypeMC
030f7aa chore: temporarily disable cascade relationship combinations (#938) by @nikophil
8238e0f fix: remove useless Configuration::boted() check (#929) by @nikophil
8e202b4 fix: TypeError FactoryCollection::create() when calling many with 0 (#925) by @jdecool
fe12d09 fix: add missing flush_once feature flag (#912) by @phasdev f991999 docs: Fix data providers phpunit link (#906) by @alexander-schranz 19ddd55 docs: in memory behavior needs PhpUnit extension (#905) by @nikophil 6a0b4ac docs: improve docs for in-memory repositories (#904) by @nikophil
How can I help you explore Laravel packages today?