Symfony, event listener, checker. Как использовать несколько event listener для одного entity

Есть один entity и 2 event listener для него, когда обновляется поле, checker проверяет изменилось ли поле и дальше отрабатывает логика. Проблема в том что listener блокирует второй listener, в итоге в втором listener не работает checker на изменение (говорит что поле не менялось) хотя в базе изменения есть.

public function postUpdate(LifecycleEventArgs $eventArgs): void
    {
        $entity = $eventArgs->getObject();
        if ($entity instance of Group) {
            $changedFields = $eventArgs->getEntityManager()->getUnitOfWork()->getEntityChangeSet($entity);
            $isChanged = $this->checker->isChanged($changedFields, ['teacher']);
            if ($isChanged) {
                $this->proceedTeacherChanges($entity);
            }

Ответы (1 шт):

Автор решения: Borislav

При заходе в Listener, Doctrine пересчитывает все изменения, т.е. делает за вас это действие EntityManager->getUnitOfWork->computeChangesSet. Этот момент важен, т.к. под капотом, она перетирает массив с данными originalEntityData, на основе которого в основном и проводит все дальнейшие проверки, вроде isChanged и т.д.

В вашем случае, происходит следующее:

  1. Doctrine поняла, что вы идете в Listener ее жизненного цикла и делает EntityManager->getUnitOfWork->computeChangesSet, в результате чего перетирает originalEntityData, тем самым фиксируя состояние ваших сущностей.
  2. Заход в первый Listener.
  3. Изменения есть, вы можете их проверить.
  4. Doctrine аналогично понимает, что вы заходите в еще один Listener ее жизненного цикла и точно так же делает перерасчет изменений, но в первом слушателе, вы не внесли никаких изменений и получается, она проверяет зафиксированное, уже рассчитанное состояние с текущими сущностями, естественно diff-а у нее нет и изменений из предыдущего слушателя, она не увидит.

Это происходит как раз из-за оного массива данных originalEntityData, во время перерасчета она его обновляет до состояния сущностей и при повторном перерасчете, не увидит из-за этого изменений.

Зачастую в документации сказано, что не нужно самому перерассчитывать changesSet в Listener-ах, т.к. он считается автоматически, а в вашем случае получается, что вы заставляете Doctrine посчитать его два раза (что именно не рекомендуется) по средствам двойной подписки.

→ Ссылка