Default entity manager always used in fixtures ?
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.
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?
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:
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 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.
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.