Symfony2 Event Listener preUpdate

1

Я настроил в моем service.yml прослушиватель событий

registerproduct.listener:
        class: App\AppBundle\Listener\RegisterProductListener
        arguments: [ @service_container ]
        tags:
            - { name: doctrine.event_listener, event: prePersist }
            - { name: doctrine.event_listener, event: preUpdate }

Мой метод decuctionProductQuantity() работает очень хорошо, когда я делаю prePersist, но не с preUpdate.

Во время обновления количество товара уменьшается, но изменений в базе данных нет.

Вот мой код для событий:

public function prePersist(LifecycleEventArgs $args)
{
    $this->decrementProductQuantity($args);
}

public function preUpdate(LifecycleEventArgs $args)
{
    $this->decrementProductQuantity($args);
}

public function decrementProductQuantity(LifecycleEventArgs $args)
{
    /** @var RegisterProduct $registerProduct */
    $registerProduct = $args->getEntity();

    if (!($registerProduct instanceof RegisterProduct))
        return;

    if ($registerProduct->getStatus() == 'inscription') {
        $product = $registerProduct->getProduct();
        $product->setQuantityStock($product->getQuantityStock() - $registerProduct->getQuantity());
    }
}

Вот мой код обновления в моем контроллере:

/**
 * @param Register $register
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function confirmAction(Request $request, Register $register)
{
    $em   = $this->getDoctrine()->getManager();

    foreach($register->getRegisterProducts() as $registerProduct){
        $registerProduct->setStatus('inscription');
        $em->persist($registerProduct);
        $em->flush();
    }       
    return $this->redirectWithMode($this->generateUrl('asc_activity_register_show', array('register' => $register->getId())));
}

Я понятия не имею, почему это работает, когда я добавляю что-то в базу данных, но не для обновления.

Спасибо за вашу помощь.

  • 0
    При обновлении сущности нет необходимости вызывать метод «сохраняться», поскольку доктрина загружает его из базы данных, и сущность уже находится в состоянии «управляемый».
  • 0
    Спасибо за основной момент
Теги:
events

3 ответа

1

На слушателе preUpdate вы должны перекомпилировать набор изменений для объекта продукта

public function decrementProductQuantity(LifecycleEventArgs $args)
{
    /** @var RegisterProduct $registerProduct */
    $registerProduct = $args->getEntity();

    if (!($registerProduct instanceof RegisterProduct))
        return;

    if ($registerProduct->getStatus() == 'inscription') {
        $product = $registerProduct->getProduct();
        $product->setQuantityStock($product->getQuantityStock() - $registerProduct->getQuantity());
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();
        $className = \Doctrine\Common\Util\ClassUtils::getClass($product);
        $classMetadata = $em->getClassMetadata($className);
        $uow->recomputeSingleEntityChangeSet($classMetadata, $product);
    }
}

Это происходит потому, что в вашем контроллере (или где-то еще) ваш код не обновляет объект продукта. Перед тем как слушатель выполняет доктрину, вычисляет наборы изменений для каждого объекта. Следовательно, в вашей доктрине слушателя preUpdate ничего не известно о продукте (потому что он не был изменен).

  • 0
    Спасибо, но это тоже не работает.
0

Поскольку я не нашел тент, я, наконец, решил сделать это прямо в контроллере:

    /**
     * @param Register $register
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function confirmAction(Request $request, Register $register)
    {
        $mode = $this->getMode($request);
        $em   = $this->getDoctrine()->getManager();

        foreach ($register->getRegisterProducts() as $registerProduct) {
            if($registerProduct->getStatus() != 'inscription'){
                $product = $registerProduct->getProduct();
                $product->setQuantityStock($product->getQuantityStock() - $registerProduct->getQuantity());
            }

            $registerProduct->setStatus('inscription');
        }

        $em->flush();

        return $this->redirectWithMode($this->generateUrl('asc_activity_register_show', array('register' => $register->getId())), $mode);
    }

Если кто-то найдет собеседника, скажите, пожалуйста.

0

Попробуйте изменить подпись вашего метода preUpdate:

use Doctrine\ORM\Event\PreUpdateEventArgs;

/.../

public function preUpdate(PreUpdateEventArgs $args)
{
    $this->decrementProductQuantity($args);
}

/.../
  • 0
    Независимо от того, какая подпись описывает метод слушателя, потому что PreUpdateEventArgs расширяет LifecycleEventArgs.
  • 0
    Да, это не работает также с PreUpdateEventArgs

Ещё вопросы

Сообщество Overcoder
Наверх
Меню