Skip to content

Recursion occurs for ProviderRegistry::getProviderFor(...) #2

@tlmcclatchey

Description

@tlmcclatchey

If a service provider requires that a class be registered as a service, the logical thing is to check for the existence of it in the bootstrap. When calling ->supports(...) the recursion starts as it asks the service manager for the (potentially) non-instantiated instance of the dependant class, at which point it will iterate through service providers and check if the current service provider supports the class - at which point it goes back to the service manager

The current workaround, placed in the ->supports(...) method, is to check if the class name matches any of the dependent service classes and, if so, return false.

We need to find a way to have something similar to the instantiation stack on the DI library, so a specific service provider is never called recursively.

class RecursionTestServiceProvider implements ServiceProviderContract, BootstrapperContract
{
    private ServiceManager $serviceManager;

    #[\Override] function bootstrap(ServiceManager $serviceManager): void
    {
        $this->serviceManager = $serviceManager;
        if (!$serviceManager->has(RecursionTestService::class))
        {
            throw new Exception('Why doesn\'t this throw?');
        }
        // WARNING: This is recursively called
    }

    #[\Override] public function supports(string $className): bool
    {
        // WARNING: This is recursively called
        return $this->serviceManager->get(RecursionTestService::class)->supports($className);
    }

    #[\Override] public function handle(string $className, array $parameters = []): object
    {
        // TODO: Implement handle() method.
    }

    #[\Override] public function isSingletonExpected(string $className): bool
    {
        // TODO: Implement isSingletonExpected() method.
    }
}

class RecursionTestService
{
    public function supports($className): bool
    {
        // WARNING: This is recursively called
    }
}

$serviceManager = new ServiceManager();
$serviceManager->providers->registerProvider(RecursionTestServiceProvider::class);;

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions