简体   繁体   English

Symfony onFlush Doctrine 监听器

[英]Symfony onFlush Doctrine Listener

Hi I have an onFlush listener:嗨,我有一个 onFlush 侦听器:

<?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:服务.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.我正在尝试将新的 zipCode 设置为用户。 But it does not seem to work.但它似乎不起作用。

Even when I'm adding a $em->persist($user) .即使我添加了$em->persist($user)

I'm looking throught this doc: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#onflush我正在看这个文档: 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).

When manipulating fields, they should be done in the preUpdaet/prePersist.操作字段时,应在 preUpdaet/prePersist 中完成。

AppBundle/EventSubscriber/EntitySubscriber.php 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服务.yml

    app.entity_subscriber:
        class: AppBundle\EventSubscriber\EntitySubscriber
        tags:
            - { name: doctrine.event_subscriber, connection: default }

If you need to create an object, persist it and flush it in your listener, then tlorens' answer won't work, as Doctrine docs mention that this must be done with an onFlush Event.如果您需要创建一个对象,将其持久化并将其刷新到您的侦听器中,那么 tlorens 的回答将不起作用,因为 Doctrine 文档提到这必须通过 onFlush 事件来完成。

Initial question was how to make it work following docs advice: 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).最初的问题是如何按照文档建议使其工作: 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). 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).

And this is a way to achieve this:这是实现这一目标的一种方式:

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

    foreach ($uow->getScheduledEntityUpdates() as $entity) {
        if ($entity instanceof User) {
            $uow->computeChangeSets();
            $changeSet = $uow->getEntityChangeSet($entity);
            // In this exemple, User has a boolean property 'enabled' and a log will be created if it is passed to 'false'
            if ($changeSet && isset($changeSet['enabled']) && $changeSet['enabled'][1] === false) {
                $log = new Log();
                $em->persist($log);
                $uow->computeChangeSet($em->getClassMetadata(get_class($log)), $log);
            }
        }
    }

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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM