Skip to content

Allow recursive container calls from factory functions#301

Merged
clue merged 2 commits intoclue:mainfrom
clue-labs:container-recursive
Feb 16, 2026
Merged

Allow recursive container calls from factory functions#301
clue merged 2 commits intoclue:mainfrom
clue-labs:container-recursive

Conversation

@clue
Copy link
Owner

@clue clue commented Feb 15, 2026

This changeset allows recursive container calls from factory functions for any variables or classes. On its own, this is rarely useful as the Container has no public API exposed at the moment. This is mostly done as an internal preparation at the moment, but may be exposed as part of our public API that allows us to reuse this logic for more classes in a follow-up.

$_ENV['X_FOO'] = 'foo';

$container = new Container([
    'X_FOO' => fn(Container $container): string => $container->getEnv('X_FOO') ?? 'default'
]);

assert($container->getEnv('X_FOO') === 'foo');

Builds on top of #290, #289, #288, #96 and others

@clue clue added this to the v0.18.0 milestone Feb 15, 2026
@clue clue requested a review from Copilot February 15, 2026 23:44
@clue clue added the new feature New feature or request label Feb 15, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables factory functions in Container to make recursive container calls (e.g., getEnv() / getObject()) by temporarily removing the active factory entry during invocation, so recursion can fall back to global env or default autowiring instead of immediately recursing into the same factory.

Changes:

  • Update Container::loadObject() to temporarily unset() the factory config entry while invoking factory closures.
  • Small internal refactor in loadVariable() to inline param loading/invocation.
  • Update/add tests to cover recursive getEnv() and recursive getObject() behavior and adjust expected error messages.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/Container.php Temporarily unsets factory entries during closure invocation to permit recursive lookups; minor invocation refactor in variable loading.
tests/ContainerTest.php Removes old “recursive class” failure test and adds new test coverage for recursive getEnv()/getObject() patterns; updates an assertion message.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 251 to +256
// invoke factory with list of parameters
$value = $params === [] ? ($this->container[$name])() : ($this->container[$name])(...$params);
// temporarily unset factory reference to allow loading recursive variables from environment
try {
unset($this->container[$name]);
$value = $factory(...$this->loadFunctionParams($closure, $depth, true, \explode("\0", $name)[0]));
} finally {
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says the factory is unset "to allow loading recursive variables from environment", but in this branch it's also enabling recursive getObject()/container lookups from within object factories. Updating the comment to reflect the broader intent would avoid confusion for future maintainers.

Copilot uses AI. Check for mistakes.
Comment on lines 2616 to 2621
public function testGetObjectReturnDefaultStdclassInstanceWhenFactoryFunctionHasRecursiveArgument(): void
{
$container = new Container([
\stdClass::class => function (\stdClass $object) { return $object; }
]);

Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New test method name uses singular "Return" but the existing naming pattern in this file appears to be "testGetObjectReturns…". Renaming to "testGetObjectReturnsDefaultStdClassInstanceWhenFactoryFunctionHasRecursiveArgument" keeps test names consistent and easier to search/scan.

Copilot uses AI. Check for mistakes.
@clue clue force-pushed the container-recursive branch from 28ef07d to 61b9193 Compare February 15, 2026 23:54
@clue clue merged commit 136319f into clue:main Feb 16, 2026
75 checks passed
@clue clue deleted the container-recursive branch February 16, 2026 00:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant