Skip to content

2.0.0-beta.2

Pre-release
Pre-release

Choose a tag to compare

@dereuromark dereuromark released this 07 May 12:37
578b826

This second beta is a hardening pass on top of 2.0.0-beta.1. Same v2 surface — see the beta.1 notes for the API at a glance.

Fixes

  • FactoryTransactionStrategy is eager again by default — beta.1 default was lazy, and so was 1.3.0–1.4.x. beta.1 inherited the lazy setupTest() that landed in 1.3.0: a connection only joined the rollback set after a Factory persisted on it. That silently broke tests that mixed Factory build with direct $table->save($entity) (the standard testValidationDefault / testFind pattern: Factory::new()->build()->toArray() then $this->Foo->save($entity)) — the direct save ran outside any transaction and leaked across test methods. The collision risk was masked from 1.3.0–1.4.x by generator-state continuity (the default generator's unique() history persisted across tests); v2's per-test reset removed that mask, so the latent leak became loud. beta.2 restores the eager default: setupTest() opens a transaction on the primary test connection (test by default; configurable via protected string $primaryConnection). Other connections are still tracked lazily via ensureTransaction() from BaseFactory::save() / saveMany(). If you want the lazy contract back (your tests persist exclusively through Factories and you want to skip transactions on connections a given test never touches): use LazyFactoryTransactionStrategy::class as the global 'fixtureStrategy', or use LazyTransactionTrait on a single test class. Both ship in this beta.
  • Generator adapters: closed silent divergences between Faker and DummyGenerator on property-style access, optional()->unique() deduping, optional() honoring the seeded randomizer, and unique enum locale/seed propagation. Locale resolution now actually honors the FixtureFactories.defaultLocale Configure key.
  • Persistence + transactions: FactoryTransactionStrategy rethrows begin() failures so silent test pollution is gone; persist mode is depth-counted so nested persists no longer end mode mid-flight; FactoryTableTracker is keyed by connection so multi-connection setups don't collapse same-named tables.
  • Association DSL: for()/has() throw on ambiguous association targets (e.g. two BelongsTo to the same parent); findBackAssociation matches on foreign key not alias, so without() strips the right side; keepDirty(false) correctly undoes propagation; mergeWithToOne no longer silently discards entities 2..N.
  • Factory API: new()/count() reject non-positive counts up front; new()/from() declare : static so subclass chains keep their entity type; nested factories' afterSave callbacks now actually fire when persisted via the parent's cascade; save([])/saveMany([]) no longer flatten an injected entity via toArray().
  • Persistence state + uniqueness: nested associated entities are now finalized before child afterSave listeners/callbacks run under FactoryTransactionStrategy; falsey unique values like 0 and '0' no longer bypass duplicate detection; temporary connection aliasing in fixture_factories persist is restored reliably after the command finishes.
  • Static reads + command parity: Factory::query() and Factory::table() now honor initialize() / configure() defaults without booting default association graphs; fixture_factories persist --dry-run --connection ... now uses the same connection alias path as a real persist; EventCollector no longer retries arbitrary runtime table-initialize failures and only retries true locator collisions.
  • Rector rules: make-to-new rewrite bails on ambiguous static types and named arguments instead of miscompiling; setDefaultTemplate-to-definition rewrite preserves static / final / abstract modifiers.
  • Internals: EventCollector registry alias is per-options-hash so two factories sharing a root table can't clobber each other's listening config; UniquenessJanitor uses strict equality and stops mutating the caller's entity; primary key generation covers mediuminteger and throws on truly unknown column types.
  • Bake/codegen: bake no longer guesses random invalid foreign-key integers for schema FKs without declared ORM associations; composite unique constraints are no longer over-tightened into per-column unique() generation; directional helper templates reject integer payload misuse instead of accidentally treating it as count().
  • Custom event managers: factory-created tables now keep the internal before-save hook and listener filtering even when you supply your own event manager.
  • CLI validation: bin/cake fixture_factories.persist now rejects malformed --number values and invalid --method targets up front instead of truncating input or crashing on non-public/argument-requiring methods.

Improvements

  • New sequenceField() helper: vary one field predictably across built or saved entities without defining a full sequence() payload for each row.
  • LazyFactoryTransactionStrategy + LazyTransactionTrait: explicit lazy opt-outs for projects whose tests persist exclusively through Factories (multi-connection optimization). Set the strategy at 'TestSuite.fixtureStrategy' for whole-suite opt-out, or use LazyTransactionTrait on individual test classes for per-class opt-out — its #[Before] hook releases the eager-begun transaction before the test body runs.
  • Docs aligned with the v2 surface: vierge-noire migration guide rewritten to target definition(GeneratorInterface) (the previous text would have produced empty factories on v2); v1→v2 upgrade guide surfaced in the sidebar; obsolete TriggerStrategy section removed from setup; missing coverage filled in for for()/has()/from()/keepDirty(), the 3-arg afterBuild/afterSave signature, sequence() cycling, and the save()/build() count-must-be-1 contract.

Full Changelog: 2.0.0-beta.1...2.0.0-beta.2