1

Тема: UniqieConstraintViolation в Doctrine2 = тлен.

Я просто приведу кусок кода:

class A {
  private $r;
  private $e;
  function __construct(Registry $r, EventDispatcherInterface $e) {...}
  function onSomthing() {
     $entity = $this->r->getMaanger()->find(123);
     $entity->setFoo('bar');
     // ...
 
     $this->e->dispatch('super_event', new Event()); // Вызывает $registry->resetManager(); неявно в другом бандле
 
     $this->r->getManager()->flush();
  }
}

Вуаля, наша энтити вообще не сохранилась. Ни тебе исключения, ни записи в лог. Happy debug!

Есть варианты как можно с этим жить?

2

Re: UniqieConstraintViolation в Doctrine2 = тлен.

dmitryk пишет:

Вызывает $registry->resetManager(); неявно в другом бандле

Ну, вообще потеря энтити после этого события — вполне нормальное и ожидаемое поведение.
А какое исключение ожидалось? «Ой, у меня тут несохраненные данные, меня нельзя ресетить»? default/smile

Собственно, самый лучший вариант — постараться не перегружать энтити менеджер в процессе работы.
Остальные варианты будут больше похожи на костыли.

И да, неявные действия хрен знает где — это то, за что я не люблю ивенты. Кирпичи для строительства хаоса.

3

Re: UniqieConstraintViolation в Doctrine2 = тлен.

relo_san пишет:
dmitryk пишет:

пишет:
Вызывает $registry->resetManager(); неявно в другом бандле

Ну, вообще потеря энтити после этого события — вполне нормальное и ожидаемое поведение.

Оно ожидаемое когда делаешь это сам, в своем приложении. А не когда кто то подписывается на ивент - ресетит менеджер а потом пару дней багу ищещь.

И все же, есть ли какие либо нормальные способы работать с доктриной, когда есть вероятность, что ентити менеджер может быть сброшен?

4

Re: UniqieConstraintViolation в Doctrine2 = тлен.

dmitryk пишет:

А не когда кто то подписывается на ивент - ресетит менеджер а потом пару дней багу ищещь.

Ну это как раз то, про что я написал — я ненавижу ивенты, потому что никогда не знаешь, какую фоновую или не очень херь какой-нибудь ивент запустит, и как это искать и дебажить. Особенно когда кода много и ивентов сотни. А есть еще люди, которые строят на них бизнес-логику. ^__^

dmitryk пишет:

нормальные способы работать с доктриной

Думаю, нет. Только костыльные. Сброс менеджера ожидаемо прекращает отслеживание сущностей, ему принадлежавших. Я даже затрудняюсь предложить какой-нибудь вменяемый костыль. Так как чтобы восстановить управление сущностью и не потерять сделанных изменений, после сброса менеджера нужно снова получить ее из базы и смержить с ранее отсоединенной при сбросе. Но для этого нужно иметь в том месте, где выполняется flush() как минимум массив всех измененных сущностей, которые требуется сохранить. И там же можно проверить их на detached статус.
Конкретно в вышеприведенном коде это сделать не очень сложно (хотя в любом случае накладно, поскольку будет выполняться запрос к базе для получения исходных сущностей), но вообще это дикий костыль и совершенно не подходит для вариантов, где flush() находится где-нибудь совсем в другом месте кода.

Имхо, но сброс менеджера, инициированный в каком-то событии — это выстрел себе в голову из гранатомета. Почти как die() в эксепшене. default/smile Людей, которые так делают, нужно отлавливать и стерилизовать.

5

Re: UniqieConstraintViolation в Doctrine2 = тлен.

Окей, предположим, что мы разобрались - так делать херово и вариантов ваще нет. Тогда что делать, когда у нас вместо Registry везде в конструкторе торчит EntityManagerInterface и при исключении из БД мы получаем "захлопнувшийся" EntityManager во всех сервисах приложения? Ведь resetManager() нас уже не спасет, ссылки на битый объект останутся.