Skip to content

feat: declarative config_overrides for FixtureLoader - #10

Merged
erikfrerejean merged 1 commit into
6from
feat/fixture-config-overrides
Jul 8, 2026
Merged

feat: declarative config_overrides for FixtureLoader#10
erikfrerejean merged 1 commit into
6from
feat/fixture-config-overrides

Conversation

@erikfrerejean

Copy link
Copy Markdown
Member

Summary

Adds a declarative config_overrides map to FixtureLoader so consuming modules can force config statics on specific classes during a fixture write — without hand-rolling a bespoke onBeforeLoad extension.

This targets the common case where a model has a write-time side effect keyed on a config static (auto-scaffolding, auto-publishing, denormalisation hooks) that must be suppressed while top-down fixtures are loaded. Previously each consumer wrote an Extension subclass; now it's YAML:

WeDevelop\E2e\Fixtures\FixtureLoader:
  config_overrides:
    My\Module\Model\Section:
      auto_scaffold: false
    My\Module\Model\Row:
      auto_scaffold: false

How it works

Each override is applied from a FixtureBlueprint beforeCreate callback. FixtureBlueprint::createObject() invokes that callback inside its own Config::nest()/unnest() window, so the value is live only for that record's write and reverts immediately afterwards — it never leaks into normal app code. Overrides are applied before the onBeforeLoad hook, so a consumer's dynamic extension can still override the same class (a later FixtureFactory::define() wins).

The onBeforeLoad hook remains for anything a static value can't express (dynamic values, non-config side effects).

Design rationale

This is configuration (which statics, what values), not behaviour — so expressing it as YAML rather than a PHP Extension is the more honest abstraction. It does not remove any flexibility: the hook is still there for the dynamic cases.

Tests

Four integration tests on FixtureLoaderTest, covering the full contract:

  • override reaches the record at write time
  • override does not leak past the load (config reverts)
  • multiple classes + multiple keys per class all apply
  • absent config_overrides is a no-op (default [])

Backed by two support models: E2eScaffoldingObject (proves real suppression behaviour) and E2eConfigProbeObject (observes the override at write time and proves no leak).

Verification

  • Full PHP suite green (59 tests, 144 assertions)
  • PHPStan clean on both the 8.3 and 8.5 configs
  • Rector clean

Consumer migration (separate repo)

A consuming module can now delete its bespoke suppression Extension + its extensions: registration and replace both with the config_overrides block above. Not included here — that's a change in the consuming repo.

Consumers that suppress a write-time side effect keyed on a config static
(auto-scaffolding, auto-publishing, denormalisation hooks) previously needed a
bespoke onBeforeLoad Extension. Expose a config_overrides map so those statics
can be forced per class in YAML instead.

Each override is applied from a FixtureBlueprint beforeCreate callback, which
runs inside FixtureBlueprint's own Config::nest()/unnest() window, so the value
is live only for that record's write and reverts immediately afterwards. It is
applied before the onBeforeLoad hook so a consumer's dynamic extension can still
override the same class.

The onBeforeLoad hook stays for anything a static value cannot express (dynamic
values, non-config side effects).
@erikfrerejean
erikfrerejean merged commit e657741 into 6 Jul 8, 2026
6 checks passed
@erikfrerejean
erikfrerejean deleted the feat/fixture-config-overrides branch July 8, 2026 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant