Open
Description
Symfony version(s) affected
6.4.2
Description
Screenshot will answer all the questions:
How to reproduce
To address the complex bug, follow these steps:
- Initiate the BugCommand.
- Place a breakpoint at \App\Repository\CategoryRepository::__construct.
- Monitor the container as it creates three instances.
https://github.com/oleg-andreyev/bug_app
Possible Solution
Update PhpDumper and alter load method to track loading status of a service.
protected function load($file, $lazyLoad = true): mixed
{
try {
if (isset($this->loading[$file])) {
$path = array_keys($this->loading);
$path = array_slice($path, array_search($file, $path, true));
$path[] = $file;
throw new \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException(
$file,
$path
);
}
$this->loading[$file] = true;
if (class_exists($class = __NAMESPACE__.'\\'.$file, false)) {
return $class::do($this, $lazyLoad);
}
if ('.' === $file[-4]) {
$class = substr($class, 0, -4);
} else {
$file .= '.php';
}
$service = require $this->containerDir.\DIRECTORY_SEPARATOR.$file;
return class_exists($class, false) ? $class::do($this, $lazyLoad) : $service;
} finally {
unset($this->loading[$file]);
}
}
as result container will throw:
In App_KernelDevDebugContainer.php line 153:
Circular reference detected for service "getCategoryRepositoryService", path: "getCategoryRepositoryService -> getDoctrineService -> getDoctrine_Orm_DefaultEntityManagerService -> getDoctrine_Dbal_DefaultConnectionService -> getDoctrine_Dbal_DefaultConnection_EventManagerService -> getDoctrine_Orm_DefaultListeners_AttachEntityListenersService -> getStofDoctrineExtensions_Listener_TreeService -> getSomeListenerService -> getProductRepositoryService -> getCategoryRepositoryService".
Additional Context
-
The reason it's not an infinite loop is that
\Symfony\Bridge\Doctrine\ContainerAwareEventManager::initializeListeners
sets$this->initialized[$eventName] = true
immediately after being called, even though the event is not initialized, which seems incorrect. -
The container does not retain any state of whether the current service is being initialized, therefore it does not throw any exceptions, though it arguably should.