Skip to content

09: Loader resolution and registration - #9

Open
nikolaystrikhar wants to merge 4 commits into
08-registrarfrom
09-loader-resolve
Open

09: Loader resolution and registration#9
nikolaystrikhar wants to merge 4 commits into
08-registrarfrom
09-loader-resolve

Conversation

@nikolaystrikhar

@nikolaystrikhar nikolaystrikhar commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Loader's collaborator resolution and registration — container-or-new, memoized — plus register(), all() and reset(). boot() and the load loop land in #11.

Stacked on #8.

The container is never required: with none set every collaborator is a plain new. Resolution is memoized and deliberately does not swap a collaborator that arrives late, since anything already holding the old instance would keep it.

  • A bad container binding was cached, with no way back out. The failure surfaced a frame later as TypeError: Loader::registrar(): Return value must be of type Registrar_Interface, stdClass returned, blaming this library rather than the binding. And reset() calls registrar(), so it threw the same TypeError — the host could not reset out of it. It throws Config_Exception before the memo now.
  • The README documented a recovery that silently destroyed the registry. A container set after the first resolve has no effect until reset() — but reset() also empties every registration, so register()set_container()reset()boot() loaded nothing, with no exception and no notice. The rule is: set the container before your first register().
  • The memoized read is narrowed to the template type. The memo map holds a different type per key, so it cannot be typed as T as a whole and the cache hit returned a bare object. Required by PHPStan level 8 (05: Static analysis in CI #5).

Verify: slic run unit — 99 tests, 144 assertions. composer test:analysis[OK] No errors.

resolve() returned object and cached whatever the container handed back,
so a mis-bound interface was stored and then failed on the accessor's
return type -- a TypeError blaming this library rather than the binding.
reset() threw the same one, so there was no way back out of it. It throws
Config_Exception at the boundary now, before the memo.

The per-accessor @var annotations are gone: verified against the pinned
PHPStan 1.12 that an object return narrowing to an interface is unreported
at level 5 and 6 either way, so they silenced nothing. resolve() carries
@template T instead.

The README pointed hosts at Loader::reset() to pick up a container set
late, but reset() also drops every registration -- following that advice
left nothing to load, silently. It now states the real rule: set the
container before the first register() call.
The memo map holds a different type per key, so it cannot be typed as T as a
whole and the cache hit returned a bare object. Required by PHPStan level 8.
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