我有一个带有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);