Какое событие Doctrine Lifecycle Event для обновления? - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть класс Listener, который при создании сообщения или объекта темы обновляет эти поля в таблице категорий:

last_post_thread_title

last_post_thread_slug

last_poster_username

last_post_body

last_post_created_at

is_last_post_op

и last_post_created_at в таблице потоков.

class LastPostListener
{
    public function postPersist(LifeCycleEventArgs $args) 
    {
        $entity = $args->getObject();
        $entityManager = $args->getObjectManager();

        $this->handleEvent($entityManager, $entity);
    }

    public function postUpdate(LifeCycleEventArgs $args) 
    {
        $entity = $args->getObject();
        $entityManager = $args->getObjectManager();

        $this->handleEvent($entityManager, $entity);
    }

    public function handleEvent($entityManager, $entity)
    {
        if (!$entity instanceof Post && !$entity instanceof Thread) {
            return;
    }

        $isPost = $entity instanceof Post;

        $thread = $isPost ? $entity->getThread() : $entity;

        $post = $isPost ? $entity : $thread;

        $category = $thread->getCategory();
        $category->setLastPostThreadTitle($thread->getTitle());
        $category->setLastPostThreadSlug($thread->getSlug());
        $category->setLastPostBody($post->getBody());
        $category->setLastPosterUsername($post->getUser()->getUsername());
        $category->setLastPostCreatedAt($post->getCreatedAt());
        $category->setIsLastPostOp(!$isPost);

        $thread->setLastPostCreatedAt($entity->getCreatedAt());

        $entityManager->persist($thread, $category);
        $entityManager->flush();
    }
}

Однако, когда EXISTING Thread или Post Entity редактируются, ранее упомянутые поля таблицы Category не обновляются.

То же самое с событиями prePersist () и preUpdate (), с или без очистки.

Конечно, можно добавить все строки $category->set непосредственно в контроллер updateфункция, но она грязная.

Какое событие следует использовать здесь или, может быть, есть какое-то другое решение?Спасибо

1 Ответ

0 голосов
/ 02 февраля 2019

Причина такого поведения объяснена в Документация доктрины с подробной информацией о разрешенных операциях внутри каждого из типов событий.Если вы посмотрите на эту статью - вы увидите, что событие preUpdate очень ограничительное, а postUpdate даже не имеет значения.Вообще говоря, основной причиной вашей текущей проблемы является попытка вызова flush(), когда flush() уже запущен.

Если вы хотите синхронизировать информацию - есть несколько способов:

  1. Вы можете использовать onFlush прослушиватель событий.Это событие дает вам доступ ко всем вычисленным изменениям, которые запланированы для фиксации, и позволит вам изучить эти изменения, чтобы решить, что обновлять.Однако это может быть не так просто, потому что вам придется иметь дело с UnitOfWork методами, которые предоставляют внутреннее представление вычисленных изменений, например, getScheduledEntityUpdates() и другими подобными методами.Также потребуется вручную пересчитать наборы изменений в случае, если вы внесете некоторые изменения в сущности в этом событии.
  2. Вы можете реализовать отдельный класс, который предоставит собственный метод flush(), который должен выглядеть примерно так:

    class CustomFlush {
        /**
         * @var EntityManager
         */
        private $em;
        /**
         * @var array
         */
        private $changes = [];
    
        public function flush($entity = null) {
            // Perform normal flushing operation
            $this->em->flush($entity);
            // If there was some changes collected - apply them
            if (!empty($this->changes)) {
                $categories = [];
                // Apply changes from $this->changes to Category entities,
                // collect them in $categories and flush separately
                if (!empty($categories)) {
                    $this->em->flush($categories);
                }
            }
        }
    
        public function preUpdate(LifeCycleEventArgs $args) {
            // Collect updates from Post and Thread and store it into $this->changes
        }
    }
    
...