DoctrineFixturesBundle icon indicating copy to clipboard operation
DoctrineFixturesBundle copied to clipboard

Default entity manager always used in fixtures ?

Open Glideh opened this issue 7 years ago • 5 comments

I have multiple connections used by multiple entity managers with separate bundles (Symfony 3.4):

doctrine:
    dbal:
        default_connection: cnx1
        connections:
            cnx1:
#              ...
            cnx1:
#              ...
#           ...
    orm:
        default_entity_manager: em1
        entity_managers:
            em1:
                connection: cnx1
                mappings:
                    FirstBundle: ~
            em2:
                connection: cnx2
                mappings:
                    SecondBundle: ~
#           ...

I have fixtures in both, but Doctrine seem to use only the default entity manager for both.

$ console doctrine:fixtures:load -n

  > purging database
  > loading FirstBundle\DataFixtures\ORM\LoadEntity1Data
  > loading FirstBundle\DataFixtures\ORM\LoadEntity2Data
[...]
  > loading SecondBundle\DataFixtures\ORM\LoadEntity3Data

In MappingException.php line 37:

The class 'SecondBundle\Entity\Entity3' was not found
  in the chain configured namespaces FirstBundle\Entity

Is there a way to help Doctrine in our fixtures guessing which manager to use ? This would avoid to have to use this for each distinct entity manager.

$ console doctrine:fixtures:load -n --em=em1 --fixtures=src/FirstBundle/DataFixtures/ORM
$ console doctrine:fixtures:load -n --em=em2 --fixtures=src/SecondBundle/DataFixtures/ORM

Maybe there is some simpler way I'm not aware of.

Glideh avatar Feb 04 '18 13:02 Glideh

At first glance, I think this should totally be possible. There is a method on the Registry class called getManagerForClass() that could be used:

https://github.com/doctrine/common/blob/a61bfddd39b887265117806e81cc6ca8da242fe1/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php#L171

Someone care to open a PR?

weaverryan avatar Mar 12 '18 13:03 weaverryan

As a possible solution, while the issue is solved, you can use groups in fixtures:

https://symfony.com/doc/master/bundles/DoctrineFixturesBundle/index.html#fixture-groups-only-executing-some-fixtures

Later, you can exec fixtures as:

$ php bin/console doctrine:fixtures:load --em em1 --group=em1 --no-interaction
$ php bin/console doctrine:fixtures:load --em em2 --group=em2 --no-interaction

This works for me on Symfony 4.2 :+1:

migueabellan avatar Jan 26 '19 11:01 migueabellan

For now, groups seem to be the only way this can be done reliably. In fixture services, you could easily have the manager registry injected and then select the appropriate manager using the getManagerForClass method that @weaverryan mentioned above. However, the fixtures will always be run in the transactional context of the entity manager provided to the command (or the default entity manager if none was provided), so you'll have to take care of transactional logic yourself.

I'm not sure what a good way to solve this would be, apart from what @migueabellan suggested above.

alcaeus avatar Jun 07 '19 11:06 alcaeus

@alcaeus Don't we just change the default behavior so when an entity manager isn't specified we try to auto detect it for the objects?

I just ran into this problem and the fix is pretty gross. I expected it to auto detect when not specifying the entity manager.

skylord123 avatar Dec 04 '19 20:12 skylord123

The fixtures only receive a single entity manager. It is up to the fixture itself to ensure that the entity manager can actually handle the entity you want to create.

When using multiple entity managers, it would definitely be advantageous to pass in the entire manager registry. I'm not sure how we can accomplish that without a hard BC break, but it could be a way to get rid of the em setting entirely.

alcaeus avatar Dec 05 '19 14:12 alcaeus