Sergii Nester
Sergii Nester

Reputation: 474

How to resolve "Circular reference detected for service" issue?

I'm trying to inject my repository service into EventListener but that leads me to following exception, which, with my basic knowledge of Symfony2, I have no idea how to resolve. Exception is:

ServiceCircularReferenceException in bootstrap.php.cache line 2129:

Circular reference detected for service "doctrine.orm.default_entity_manager", path: "doctrine.orm.default_entity_manager -> doctrine.dbal.default_connection -> person.connect.listener -> tag.repository.service".

And here is how I've declared repository and listener:

tag.repository.service:
    class: Application\Bundle\PersonBundle\Entity\TagRepository
    factory: ["@doctrine", getRepository]
    arguments: [ Application\Bundle\PersonBundle\Entity\Tag ]

person.connect.listener:
    class: Application\Bundle\PersonBundle\EventListener\ConnectListener
    arguments:
        tokenStorage: "@security.token_storage"
        tagRepo: "@tag.repository.service"
    tags:
        - { name: doctrine.event_listener, event: postPersist, connection: default }

Most answers, that I've able to find, suggest injecting service container, but I really don't want do that. Is there any way to resolve this properly?

UPD: Here is the code of the listener. Everything worked fine until I've tried to inject TagRepository

class ConnectListener
{
/**
 * @var TokenStorage
 */
private $tokenStorage;

/**
 * @var TagRepository
 */
private $tagRepo;

/**
 * @param TokenStorage $tokenStorage
 * @param TagRepository $tagRepo
 */
public function __construct(TokenStorage $tokenStorage, TagRepository $tagRepo)
{
    $this->tokenStorage = $tokenStorage;
}
/**
 * @param LifecycleEventArgs $args
 * @return void
 */
public function postPersist(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();
    $entityManager = $args->getEntityManager();

    if ($entity instanceof Person) {
        $user = $this->tokenStorage->getToken()->getUser();
        $visibility = new PersonVisibility($entity, $user);
        $visibility->setVisibilityType(PersonVisibility::VT_CREATED);
        $entityManager->persist($visibility);
        $entityManager->flush();
    }
}
}

Upvotes: 6

Views: 12601

Answers (2)

Fabien Salles
Fabien Salles

Reputation: 1181

Yo can also change your declaration of your repository, don't use the factory and use one of these 2 methods.

This will avoid the circular reference and will be cleaner than use the EntityManager class.

Upvotes: 0

Andrii Kucherenko
Andrii Kucherenko

Reputation: 176

As far as TagRepository is descendant of EntityRepository try obtaining its instance in postPersist event. Like this:

// using full classname:
$tagRepo = $entityManager->getRepository("Application\Bundle\PersonBundle\Entity\TagRepository");
// alternatively:
$tagRepo = $entityManager->getRepository("ApplicationPersonBundle:Tag");

Upvotes: 1

Related Questions