@HellWalk

Как подменить используемый EntityManager?

Есть ли способ через конфиг симфони подменить используемый по умолчанию Doctrine\ORM\EntityManager например на App\Proxy\EntityManagerProxy?

Т.е. указываю EntityManagerInterface в конструкторе, и контейнер понимал, что нужно создать App\Proxy\EntityManagerProxy (реализующий этот же интерфейс), а не стандартный Doctrine\ORM\EntityManager
  • Вопрос задан
  • 198 просмотров
Решения вопроса 2
@HellWalk Автор вопроса
Не смотря на наличие документации на которую сослался Денис Дерепко, она мало помогает в задаче подменить именно EntityManager, и именно когда к нему идет обращение в зависимостях через EntityManagerInterface.

По этому отдельным ответом пишу решение:

config/services.yaml:
App\Proxy\EntityManagerProxy:
    decorates: 'doctrine.orm.entity_manager'


Proxy-обертка (здесь оставив за скобками почему в документации декоратор, а в моем случае proxy) с нужным функционалом - чтобы EntityManager переподключался в базе в случае потери соединения с базой (а доктрина закрывает соединение в случае любой SQL-ошибки):

class EntityManagerProxy implements EntityManagerInterface
{
    private ObjectManager $entityManager;
    private ManagerRegistry $doctrine;

    public function __construct(ObjectManager $entityManager, ManagerRegistry $doctrine)
    {
        $this->entityManager = $entityManager;
        $this->doctrine = $doctrine;
    }

    /**
     * @param $object
     * @return void
     * @throws Exception
     */
    public function persist($object): void
    {
        $this->correctionConnect();
        $this->entityManager->persist($object);
    }

    /**
     * @return void
     * @throws Exception
     */
    public function flush(): void
    {
        $this->correctionConnect();
        $this->entityManager->flush();
    }


    private function correctionConnect(): void
    {
        // Для ошибок когда падает сама база или соединение с ней, например:
        // SQLSTATE[57P01]: Admin shutdown: 7 FATAL:  terminating connection due to administrator command
        // SQLSTATE[08006] [7] could not translate host name "postgres" to address: Temporary failure in name resolution
        // (например, когда на время падает контейнер с postgres)
        if ($this->entityManager->getConnection()->ping() === false) {
            $this->entityManager->getConnection()->close();
            $this->entityManager->getConnection()->connect();
        }

        // Для ошибки "The EntityManager is closed" (например, при ошибки SQL-запроса)
        if (!$this->entityManager->isOpen()) {
            $this->doctrine->resetManager();
            $this->entityManager = $this->doctrine->getManager();
        }
    }
    
    // Все другие методы для EntityManagerInterface перебрасываются напрямую на базовый EntityManager
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы