如何在DBALException之后重新打开Doctrine Entity Manager


How to reopen Doctrine Entity Manager after DBALException

我有一个带有Symfony 2的控制台应用程序,该脚本在cron(终端)上运行。但是,在 ''Doctrine''DBAL''DBALException 之后,脚本会抛出 N ''Doctrine''ORM''ORMException,并显示消息"The EntityManager is closed"。

这是部分脚本:

try {
    $this->getDoctrine()->getConnection()->beginTransaction();
    // ...
    $manager = $this->getDoctrine()->getManager();
    $entity = new Post();
    $entity
        ->setAuthor($author)
        ->setTitle($title)
        ->setContent($content)
    ;
    $manager->persist($entity);
    $manager->flush();
    $this->getDoctrine()->getConnection()->commit();
    return $entity->getId();
} catch ('Doctrine'DBAL'DBALException $e) {
    $this->getDoctrine()->resetManager();
    $output->writeln(sprintf(
        '<error>[!] %s (%s) the post could not be created "%s"</error>',
        get_class($e),
        date('Y-m-d H:i:s'),
        $e->getMessage()
    ));
    return false;
} catch ('Exception $e) {
    $this->getDoctrine()->getConnection()->rollback();
    $output->writeln(sprintf(
        '<error>[!] %s (%s) the post could not be created "%s"</error>',
        get_class($e),
        date('Y-m-d H:i:s'),
        $e->getMessage()
    ));
    return false;
}

如何解决?

您可以像这样手动重置实体管理器:

//...
} catch ('Doctrine'DBAL'DBALException $e) {
    $manager = $this->getDoctrine()->getManager();
    if (!$manager->isOpen()) {
        $manager = $manager->create(
            $manager->getConnection(),
            $manager->getConfiguration()
        );
    }
    $output->writeln(sprintf(
        '<error>[!] %s (%s) the post could not be created "%s"</error>',
        get_class($e),
        date('Y-m-d H:i:s'),
        $e->getMessage()
    ));
    return false;
} 
//...

在Symfony 5上,我以这种方式重新打开了连接:

} catch ('Doctrine'DBAL'Driver'Exception $e) {
     /** @var 'Doctrine'Persistence'ManagerRegistry $managerRegistry */
     $managerRegistry->resetManager();
} 

我见过其他情况,他们使用返回值resetManager(): ObjectManager作为新的实体管理器,而不是继续使用相同的实体管理器。但这是不必要的,您可以继续使用相同的实体管理器。

如果你在项目中使用 PSR-15 和 PHP-DI,试试这个中间件:

https://github.com/autorusltd/doctrine-persistent-entity-manager-middleware

你可以像这样使用它:

use Arus'Middleware'DoctrinePersistentEntityManagerMiddleware;
$requestHandler->add(new DoctrinePersistentEntityManagerMiddleware($container));
$requestHandler->handle($request);