DEV Community

Cover image for EntityManager is closed : Recovering from Doctrine exceptions
Arthur TOUZARD
Arthur TOUZARD

Posted on • Edited on

EntityManager is closed : Recovering from Doctrine exceptions

TD;LR you can't use the doctrine entity manager after a rollback happened. To do that, use doctrine managerRegistry to reset the entityManager

Handling errors is an important part of engineering.
Working with Doctrine ORM usually make our life way simpler but when it comes to doing things after a database error, things tends to complicate.

Let's say we want to save something but keep a trace if we encounter and error :

<?php

$something = new Something();

try {
    $this->entityManager->persist($something);
    $this->entityManager->flush();
} catch (\Throwable $exception) {
    $something->isErroneous();
    $something->setErrorMessage($exception->getMessage());

    $this->entityManager->flush();
}
Enter fullscreen mode Exit fullscreen mode

If we encounter a SQL error raised by our database, the following exception will appear :

In EntityManagerClosed.php line 11:

  The EntityManager is closed.
Enter fullscreen mode Exit fullscreen mode

You might think "Why the F is my entity manager closed ?".
Well, doctrine automatically closes it on error :

// Doctrine\ORM\UnitOfWork.php:
} catch (Throwable $e) {
    $this->em->close();

    if ($conn->isTransactionActive()) {
        $conn->rollBack();
    }

    $this->afterTransactionRolledBack();

    throw $e;
}
Enter fullscreen mode Exit fullscreen mode

In order to properly do that, we will leverage the Doctrine\Persistence\ManagerRegistry with the transactional system :

<?php

$something = new Something();

$this->entityManager->beginTransaction();

try {
    $this->entityManager->persist($something);
    $this->entityManager->flush();
    $this->entityManager->commit();
} catch (\Throwable $exception) {
    $this->entityManager->rollback();
    $this->managerRegistry->resetManager();

    $something->isErroneous();
    $something->setErrorMessage($exception->getMessage());

    $this->entityManager->persist($something);
    $this->entityManager->flush();
    $this->entityManager->commit();
}

Enter fullscreen mode Exit fullscreen mode

Problem solved ¯_(ツ)_/¯

Top comments (0)