1

I'm refactoring the code in one of my Controller to put it in a service.

In the Controller the entity manager is targeting a db connection called legacy.

The problem is, I did not injected the Entity Manager in my service but just the OrderRepository.

How can I target the good db connection with the repository in my service without the Entity Manager?

OrderController

// In my Controller
$em = $this->getDoctrine()->getManager('legacy');
$em->persist($order);
$em->flush();

OrderService

// In my Service
public function __construct(OrderRepository $orderRepository)
{
  $this->orderRepository = $orderRepository;
}

public function updateOrderStatus(Order $order)
{
   // some code ...

   $this->orderRepository->save($order);
}
4
  • Not clear to me what you are asking. If this is a Doctrine repository then the repository itself has direct access to the entity manager. Commented Sep 24, 2018 at 12:52
  • Hi @Kevin, may I ask why would you not want the EntityManager to be injected? Commented Sep 24, 2018 at 13:37
  • 1
    @AnjanaSilva Because it is a bad practice matthiasnoback.nl/2014/05/… Commented Sep 24, 2018 at 13:41
  • @Kevin I agree. Commented Sep 24, 2018 at 15:21

2 Answers 2

3

Based on some comments it would appear that the basic issue is having multiple entity managers. Nowadays there is a great deal of automated functionality which works well for one entity manager but no so much for multiple managers.

You basically need to define your services manually.

# services.yaml

# assume we have 
# doctrine.orm.default_entity_manager and
# doctrine.orm.legacy_entity_manager 
# already defined through configuration

# define legacy repository
order_repository.legacy:
    class:  Whatever\Repository\OrderRepository
    factory: ['doctrine.orm.legacy_entity_manager', 'getRepository']
    arguments:  
        - 'Whatever\Entity\Order'

# define default repository
order_repository.default:
    class:  Whatever\Repository\OrderRepository
    factory: ['doctrine.orm.default_entity_manager', 'getRepository']
    arguments:  
        - 'Whatever\Entity\Order'

# then your service
Whatever\Service\MyService:
    '@order_repository.legacy'

And you should be good to go. Note that your repository needs to extend EntityRepository and not the doctrine bundle's ServiceEntityRepository.

And if you feel this is too much work then just inject the doctrine bundle's entity manager registry and do what the ControllerTrait::getDoctrine($name) does.

Sign up to request clarification or add additional context in comments.

Comments

0

You must forgot that you can always get the entity manager inside your repository just like this:

$em = $this->getEntityManager();

then you can use it normally calling persist, flush etc.

Note that the Repository class itself is agnostic to functionalities of the database access layer like insert or update so it should call entity manager to execute them.

4 Comments

yes but I cannot pass a db connection name with this entity manager. But I can with the one available in a Controller: public function getManager($name = null);
@Kevin - I thought that might be the issue. You have multiple entity managers correct? The thing to understand is that each Doctrine repository is directly created from an entity manager. Repositories are not standalone. You will need to manually define your repository service definitions to specify which manager they get created from. And then you will need to manually define your service definition to insert the correct repository. Or you could just inject the doctrine service and pull the manager/repository from it just like the controller does.
@Cerad Yes I have multiple Entity Manager. You will need to manually define your repository service definitions to specify which manager they get created from. And then you will need to manually define your service definition to insert the correct repository ... Mmhh I don't really understand how can I do that.
Search a bit for "how to define repositories as services" until you find an example of doing one using the container's factory functionality. Basically you need to setup a call to $entityManager::getRepository($entityName). We are spoiled a bit because with autowire and the ServiceRepository base class we no longer need to do this when only one manager is available. Have to go a bit old schooll to support multiple managers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.