Symfony onFlush Doctrine Listener

2019-07-14 03:00发布

Hi I have an onFlush listener:

<?php

namespace FM\AppBundle\EventListener;

use FM\AdminBundle\Entity\Address\DeliveryAddress;
use Doctrine\ORM\Event\OnFlushEventArgs;

class DeliveryAddressListener
{
    /**
     * @param OnFlushEventArgs $args
     */
    public function onFlush(OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        foreach ($uow->getScheduledEntityUpdates() as $entity) {
            if ($entity instanceof DeliveryAddress) {
                $this->addPostalToUser($entity, $args);
            }
        }
    }

    /**
     * @param DeliveryAddress  $deliveryAddress
     * @param OnFlushEventArgs $args
     */
    public function addPostalToUser(DeliveryAddress $deliveryAddress, OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $user = $deliveryAddress->getOwner();

        $user->setPostalCode($deliveryAddress->getZipCode());
    }
}

service.yml:

delivery_address.listener:
    class: FM\AppBundle\EventListener\DeliveryAddressListener
    tags:
        - { name: doctrine.event_listener, event: onFlush }

I'm trying to set the new zipCode to the User. But it does not seem to work.

Even when I'm adding a $em->persist($user).

I'm looking throught this doc: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#onflush

But I don't understand how I can make it works with this explanation:

If you create and persist a new entity in onFlush, then calling EntityManager#persist() is not enough. You have to execute an additional call to $unitOfWork->computeChangeSet($classMetadata, $entity).

2条回答
倾城 Initia
2楼-- · 2019-07-14 03:39

When manipulating fields, they should be done in the preUpdaet/prePersist.

AppBundle/EventSubscriber/EntitySubscriber.php

namespace AppBundle\EventSubscriber;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;

class EntitySubscriber implements EventSubscriber
{
    private $now;

    public function __construct()
    {
        $this->now = \DateTime::createFromFormat('Y-m-d h:i:s', date('Y-m-d h:i:s'));
    }

    public function getSubscribedEvents()
    {
        return [
            'prePersist',
            'preUpdate'
        ];
    }

    public function prePersist(LifecycleEventArgs $args)
    {
        $entity        = $args->getEntity();
        $entityManager = $args->getEntityManager();

        if (method_exists($entity, 'setCreatedAt')) {
            $entity->setUpdatedAt($this->now);
        }

        if (method_exists($entity, 'setUpdatedAt')) {
            $entity->setUpdatedAt($this->now);
        }
    }

    public function preUpdate(LifecycleEventArgs $args)
    {
        $entity        = $args->getEntity();
        $entityManager = $args->getEntityManager();

        if (method_exists($entity, 'setUpdatedAt')) {
            $entity->setUpdatedAt($this->now);
        }
    }
}

services.yml

    app.entity_subscriber:
        class: AppBundle\EventSubscriber\EntitySubscriber
        tags:
            - { name: doctrine.event_subscriber, connection: default }
查看更多
啃猪蹄的小仙女
3楼-- · 2019-07-14 03:41

Well it works when I use that:

// Remove event, if we call $this->em->flush() now there is no infinite recursion loop!
$eventManager->removeEventListener('onFlush', $this);

My Listener

namespace FM\AppBundle\EventListener;

use FM\AdminBundle\Entity\Address\DeliveryAddress;
use Doctrine\ORM\Event\OnFlushEventArgs;

class DeliveryAddressListener
{
    /**
     * @param OnFlushEventArgs $args
     */
    public function onFlush(OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();
        $eventManager = $em->getEventManager();

        // Remove event, if we call $this->em->flush() now there is no infinite recursion loop!
        $eventManager->removeEventListener('onFlush', $this);

        foreach ($uow->getScheduledEntityUpdates() as $entity) {
            if ($entity instanceof DeliveryAddress) {
                $this->addPostalToUser($entity, $args);
            }
        }
    }

    /**
     * @param DeliveryAddress  $deliveryAddress
     * @param OnFlushEventArgs $args
     */
    public function addPostalToUser(DeliveryAddress $deliveryAddress, OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $user = $deliveryAddress->getOwner();

        $user->setPostalCode($deliveryAddress->getZipCode());
        $em->flush();
    }
}
查看更多
登录 后发表回答