Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[DI] doctrine entity manager build order #48895

Copy link
Copy link
Closed
@axi

Description

@axi
Issue body actions

Symfony version(s) affected

5.4.17

Description

After upgrading to symfony/dependency-injection 5.4.17, several users (including me) encountered the following exception when clearing cache:

In MissingMappingDriverImplementation.php line 11:
                                                                                                                       
  [Doctrine\ORM\Exception\MissingMappingDriverImplementation]                                                          
  It's a requirement to specify a Metadata Driver and pass it to Doctrine\ORM\Configuration::setMetadataDriverImpl().  

Exception trace:
  at /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/Exception/MissingMappingDriverImplementation.php:11
 Doctrine\ORM\Exception\MissingMappingDriverImplementation::create() at /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:162
 Doctrine\ORM\EntityManager->__construct() at /var/www/app/var/cache/dev/ContainerXpmlFIp/srcApp_KernelDevDebugContainer.php:4128

Rolling back to 5.4.16 fix the exception.
We started discussing this in the #48814 issue but it finaly doesn't look like the same problem.

------ Following is the first comment from #48814 by @julienfastre ----------------

I experience a problem which may be similar, with a complex configuration of EntityManagerInterface.

With symfony/dependency-injection on 5.4.17, the kernel "prepares" the EntityManager like this:

    /**
     * Gets the public 'doctrine.orm.default_entity_manager' shared service.
     *
     * @return \Doctrine\ORM\EntityManager
     */
    protected function getDoctrine_Orm_DefaultEntityManagerService($lazyLoad = true)
    {
        $a = ($this->services['doctrine.dbal.default_connection'] ?? $this->getDoctrine_Dbal_DefaultConnectionService());

        if (isset($this->services['doctrine.orm.default_entity_manager'])) {
            return $this->services['doctrine.orm.default_entity_manager'];
        }
        $b = new \Doctrine\ORM\Configuration();

        $c = new \Doctrine\Persistence\Mapping\Driver\MappingDriverChain();

        $d = ($this->privates['doctrine.orm.default_annotation_metadata_driver'] ?? $this->getDoctrine_Orm_DefaultAnnotationMetadataDriverService());

        $c->addDriver($d, 'App\\Entity');
        $c->addDriver($d, 'Chill\\MainBundle\\Entity');
        $c->addDriver($d, 'Chill\\PersonBundle\\Entity');
        $c->addDriver($d, 'Chill\\CustomFieldsBundle\\Entity');
        $c->addDriver($d, 'Chill\\ActivityBundle\\Entity');
        $c->addDriver($d, 'Chill\\DocStoreBundle\\Entity');
        $c->addDriver($d, 'Chill\\DocGeneratorBundle\\Entity');
        $c->addDriver($d, 'Chill\\AsideActivityBundle\\Entity');
        $c->addDriver($d, 'Chill\\CalendarBundle\\Entity');
        $c->addDriver($d, 'Chill\\TaskBundle\\Entity');
        $c->addDriver($d, 'Chill\\ThirdPartyBundle\\Entity');
        $c->addDriver($d, 'Chill\\BudgetBundle\\Entity');

        // here, an exception is thrown because the configuration ($b) does not contains a mapping driver,
       // which is added later in the function
        $this->services['doctrine.orm.default_entity_manager'] = $instance = new \Doctrine\ORM\EntityManager($a, $b);

        (new \Doctrine\Bundle\DoctrineBundle\ManagerConfigurator([], []))->configure($instance);

        $b->setEntityNamespaces(['App' => 'App\\Entity', 'ChillMainBundle' => 'Chill\\MainBundle\\Entity', 'ChillPersonBundle' => 'Chill\\PersonBundle\\Entity', 'ChillCustomFieldsBundle' => 'Chill\\CustomFieldsBundle\\Entity', 'ChillActivityBundle' => 'Chill\\ActivityBundle\\Entity', 'ChillDocStoreBundle' => 'Chill\\DocStoreBundle\\Entity', 'ChillDocGeneratorBundle' => 'Chill\\DocGeneratorBundle\\Entity', 'ChillAsideActivityBundle' => 'Chill\\AsideActivityBundle\\Entity', 'ChillCalendarBundle' => 'Chill\\CalendarBundle\\Entity', 'ChillTaskBundle' => 'Chill\\TaskBundle\\Entity', 'ChillThirdPartyBundle' => 'Chill\\ThirdPartyBundle\\Entity', 'ChillBudgetBundle' => 'Chill\\BudgetBundle\\Entity']);
        $b->setMetadataCache(new \Symfony\Component\Cache\Adapter\ArrayAdapter());
        $b->setQueryCache(($this->privates['cache.doctrine.orm.default.query'] ?? $this->getCache_Doctrine_Orm_Default_QueryService()));
        $b->setResultCache(($this->privates['cache.doctrine.orm.default.result'] ?? $this->getCache_Doctrine_Orm_Default_ResultService()));

       /// here is added the missing metadata driver
        $b->setMetadataDriverImpl($c);

        $b->setProxyDir(($this->targetDir.''.'/doctrine/orm/Proxies'));
        $b->setProxyNamespace('Proxies');
        $b->setAutoGenerateProxyClasses(true);
        $b->setSchemaIgnoreClasses([]);
        $b->setClassMetadataFactoryName('Doctrine\\ORM\\Mapping\\ClassMetadataFactory');
        $b->setDefaultRepositoryClassName('Doctrine\\ORM\\EntityRepository');
        $b->setNamingStrategy(new \Doctrine\ORM\Mapping\DefaultNamingStrategy());
        $b->setQuoteStrategy(new \Doctrine\ORM\Mapping\DefaultQuoteStrategy());
        $b->setEntityListenerResolver(($this->services['doctrine.orm.default_entity_listener_resolver'] ?? $this->getDoctrine_Orm_DefaultEntityListenerResolverService()));
        $b->setRepositoryFactory( /* etc. etc. */)
        $b->addCustomHydrationMode('chill_flat_hierarchy_list', 'Chill\\MainBundle\\Doctrine\\ORM\\Hydration\\FlatHierarchyEntityHydrator');
        $b->addCustomStringFunction('GET_PERSON_ADDRESS_ADDRESS_ID', 'Chill\\PersonBundle\\Doctrine\\DQL\\AddressPart\\AddressPartAddressId');

        // ...
        // add a lot of other custom function there ...
       // ...

        return $instance;
    }

This cause a bug because the EntityManager instance is created too early:

In MissingMappingDriverImplementation.php line 11:
                                                                                                                       
  [Doctrine\ORM\Exception\MissingMappingDriverImplementation]                                                          
  It's a requirement to specify a Metadata Driver and pass it to Doctrine\ORM\Configuration::setMetadataDriverImpl().  
                                                                                                                       

Exception trace:
  at /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/Exception/MissingMappingDriverImplementation.php:11
 Doctrine\ORM\Exception\MissingMappingDriverImplementation::create() at /var/www/app/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:162
 Doctrine\ORM\EntityManager->__construct() at /var/www/app/var/cache/dev/ContainerXpmlFIp/srcApp_KernelDevDebugContainer.php:4128

If I move those two lines at the end of the method, just before the return $instance;, it does work:

    protected function getDoctrine_Orm_DefaultEntityManagerService($lazyLoad = true)
    {
        // ...
        
        $this->services['doctrine.orm.default_entity_manager'] = $instance = new \Doctrine\ORM\EntityManager($a, $b);

        (new \Doctrine\Bundle\DoctrineBundle\ManagerConfigurator([], []))->configure($instance);

        return $instance;
    }

If I downgrade symfony/dependency-injection to 5.4.16 (composer require symfony/dependency-injection 5.4.16), the container is compiled in this manner, and the problem is fixed.

EDIT 30/12/22 add comment in code block and correct version mismatch

Originally posted by @julienfastre in #48814 (comment)

How to reproduce

I didn't succed to create a reproducer.

------ Following is a comment from #48814 by @HeinDR who tracked the bug down to a change from a commit ----------------

I also experience a similar problem with the doctrine configuration when I add an extra entity manager. After the update te symfony/dependency-injection 5.4.17 I get this error:
It's a requirement to specify a Metadata Driver and pass it to Doctrine\ORM\Configuration::setMetadataDriverImpl().
when I clear the cache.

I could trace the problem back to commit 58f2988 where in the PhpDumper the edge->isLazy() check is removed in favor of checks further down the foreach.

private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$loops = [], array $path = [], bool $byConstructor = true): void
    {
        $path[$sourceId] = $byConstructor;
        $checkedNodes[$sourceId] = true;
        foreach ($edges as $edge) {
            $node = $edge->getDestNode();
            $id = $node->getId();
            if ($sourceId === $id || !$node->getValue() instanceof Definition || $edge->isWeak()) {
                continue;
            }
       //..
    }

When I add the edge->isLazy() check and manualy delete the cache the error is gone.

private function collectCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$loops = [], array $path = [], bool $byConstructor = true): void
    {
        $path[$sourceId] = $byConstructor;
        $checkedNodes[$sourceId] = true;
        foreach ($edges as $edge) {
            $node = $edge->getDestNode();
            $id = $node->getId();
            if ($sourceId === $id || !$node->getValue() instanceof Definition || $edge->isLazy() || $edge->isWeak()) {
                continue;
            }
       //..
    }

Originally posted by @HeinDR in #48814 (comment)

Possible Solution

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.