Reputation: 1005
I have a weird problem with my custom Doctrine2 repository.
I have a DELETE-controller, which looks basically like this:
public function deleteAction(MyEntity $myEntity, MyEntityRepository $myEntityRepository)
{
$myEntityRepository->remove($myEntity);
$myEntityRepository->flushEntityManager();
return new JsonResponse(['message' => 'Bye bye!']);
}
And the Repository's remove method looks like this:
public function remove(MyEntity $entity): MyEntityRepository
{
$this->getEntityManager()->remove($entity);
return $this;
}
This has worked before, but now, I get an Exception:
Detached entity AppBundle\Entity\MyEntity@000000003b458c32000000007fd2994a cannot be removed
I really don't know, why the EntityManager inside the Repository thinks, the Entity is detached. When I inject the EntityManager directly to my controller, everything is okay:
public function deleteAction(MyEntity $myEntity, EntityManagerInterface $em)
{
$em->remove($myEntity);
$em->flush();
return new JsonResponse(['message' => 'Bye bye!']);
}
Any ideas on this? Why is the EntityManager I get from Doctrine\ORM\EntityRepository->getEntityManager() different from the one that is injected into my controller?
P.S. My other DELETE-actions don't have this problem and they all use their identical custom repositorys. This drives me crazy.
Edit: dumping $this->getEntityManager()
within the repository comes up with:
EntityManager {#627 ▼
-config: Configuration {#461 ▶}
-conn: Connection {#471 ▶}
-metadataFactory: ClassMetadataFactory {#618 ▶}
-unitOfWork: UnitOfWork {#493 ▶}
-eventManager: ContainerAwareEventManager {#511 ▶}
-proxyFactory: ProxyFactory {#588 ▶}
-repositoryFactory: DefaultRepositoryFactory {#619 ▶}
-expressionBuilder: null
-closed: false
-filterCollection: FilterCollection {#598 ▶}
-cache: null
}
while dumping $em
within the controller comes up with
DoctrineORMEntityManager_00000000644c03b80000000000dac8cc6811571fd60520ff7ea135d840b51abe {#410 ▼
-valueHolder59cfe1676bb7b138763071: EntityManager {#664 …11}
-initializer59cfe1676bb84613288121: null
}
Upvotes: 2
Views: 664
Reputation: 1005
I created a new empty Symfony project to reproduce the problem step by step. I got to the same error, when I implemented my entity listener, which has a helper class as a dependency, which itself has the MyEntityRepository as a dependency. Removing this dependency removed the problem with the detached Entity.
Some further investigation later, I realized, that EntityManager instances that are injected are sometimes new instances. To get the main instance injected (and to remove circular reference errors by the way), you can tag the entity listener service to be lazy:
AppBundle\EventListener\MyEntityListener:
autowire: true
autoconfigure: true
# the service must be public, when it's tagged lazy
public: true
tags:
- { name: doctrine.orm.entity_listener, lazy: true }
This lazy stuff solves my problem!
But I still do not understand, why I get another instance of EntityManager injected to my repository, when another service gets this repository injected.
For the record, MyEntityRepository configuration:
AppBundle\Entity\Repository\MyEntityRepository:
autowire: false
autoconfigure: true
public: false
factory: ['@doctrine.orm.default_entity_manager', getRepository]
arguments:
- AppBundle\Entity\MyEntity
The listerner service:
class MyEntityListener
{
/** @var MyEntityHelper */
protected $myEntityHelper;
public function __construct(MyEntityHelper $myEntityHelper)
{
$this->myEntityHelper = $myEntityHelper;
}
// ...
}
and the helper service:
class MyEntityHelper
{
/** @var MyEntityRepository */
protected $myEntityRepository;
// this injection of MyEntityRepository creates the problem
// with the two instances of the EntityManager
// unless the MyEntityListener is tagged as lazy
public function __construct(MyEntityRepository $myEntityRepository)
{
$this->myEntityRepository = $myEntityRepository;
}
// ...
}
Upvotes: 2