Doctrine 我应该使用什么事件来检测实体再次被持久化但没有被更改?

Doctrine 我应该使用什么事件来检测实体再次被持久化但没有被更改?,doctrine,symfony,Doctrine,Symfony,我想在更新实体时触发一个事件,即使数据没有更改。那么,我应该使用什么事件 提醒:我想访问实体数据,因此我不能使用onFlush。此外,由于未更改实体数据,因此不会触发preUpate或positionpdate 您可以在service manager中集中实体的存储。 在这种情况下,经理试图派遣一个一般事件 use Symfony\Component\EventDispatcher\GenericEvent; ... ... public function persistAndFlush

我想在更新实体时触发一个事件,即使数据没有更改。那么,我应该使用什么事件

提醒:我想访问实体数据,因此我不能使用
onFlush
。此外,由于未更改实体数据,因此不会触发
preUpate
positionpdate


您可以在service manager中集中实体的存储。 在这种情况下,经理试图派遣一个一般事件

use Symfony\Component\EventDispatcher\GenericEvent;
...
...
    public function persistAndFlush($entity)
    {
        $this->em->persist($entity);
        $this->em->flush();

        //dispatch an event
        $event = new GenericEvent($entity, array('course_history' => 1));
        $this->dispatcher->dispatch(YourClassEvents::UPDATE_ENTITY, $event);
    }
然后,您可以创建一个listner来侦听此一般事件

编辑 更多详细信息

假设我们有实体产品

  • 创建服务管理器
service.xml

在service.xml中添加侦听器的定义


您可以在service manager中集中实体的数据。 在这种情况下,经理试图派遣一个一般事件

use Symfony\Component\EventDispatcher\GenericEvent;
...
...
    public function persistAndFlush($entity)
    {
        $this->em->persist($entity);
        $this->em->flush();

        //dispatch an event
        $event = new GenericEvent($entity, array('course_history' => 1));
        $this->dispatcher->dispatch(YourClassEvents::UPDATE_ENTITY, $event);
    }
然后,您可以创建一个listner来侦听此一般事件

编辑 更多详细信息

假设我们有实体产品

  • 创建服务管理器
service.xml

在service.xml中添加侦听器的定义


我看到了问题所在。您希望在更新后访问实体,但该实体不是真正的更新。显然,您在这里使用了DQL查询,正如您正确提到的。问题是,条令并不真正知道对象已被更改-查询可能有点复杂,因此对象标识符可能会被隐藏。甚至不知道(在MySQL的情况下)

一些RDBMs有
RETURNING
子句,允许您查看更新结果,但它不是DB抽象的,因此无法从DQL开箱即用访问

您可以使用本机SQL查询或执行其他技巧来获取更新的行

如果查询不是性能关键的,我宁愿建议使用一些软件(php端)进行简单的处理

如果是,我认为这是不可能的。如果您了解用例的更多细节,可以讨论解决方法


也就是说,您可以使用迭代的方法对EM中缓存的所有实体进行迭代,并检查vesrion是否已更改。

我看到了这里的问题。您希望在更新后访问实体,但该实体不是真正的更新。显然,您在这里使用了DQL查询,正如您正确提到的。问题是,条令并不真正知道对象已被更改-查询可能有点复杂,因此对象标识符可能会被隐藏。甚至不知道(在MySQL的情况下)

一些RDBMs有
RETURNING
子句,允许您查看更新结果,但它不是DB抽象的,因此无法从DQL开箱即用访问

您可以使用本机SQL查询或执行其他技巧来获取更新的行

如果查询不是性能关键的,我宁愿建议使用一些软件(php端)进行简单的处理

如果是,我认为这是不可能的。如果您了解用例的更多细节,可以讨论解决方法

也就是说,您可以使用iterate对EM中缓存的所有实体进行迭代,并检查vesrion是否已更改

<service id="yourdomain.product_manager" class="Domain\YourBundle\Service\ProductManager">
    <argument type="service" id="doctrine.orm.entity_manager"/>
    <argument type="service" id="event_dispatcher"/>
</service>
namespace Domain\YourBundle\Manager;

use Doctrine\ORM\EntityManager;
use Domain\YourBundle\Entity\Product;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;

class ProductManager
{
    /**
     * @var EntityManager
     */
    protected $em;
    /**
     * @var EventDispatcherInterface
     */
    protected $dispatcher;
    /**
     * @param EntityManager $em
     */
    public function __construct(EntityManager $em, EventDispatcherInterface $dispatcher)
    {
        $this->em = $em;
        $this->dispatcher = $dispatcher;
    }

    public function persistAndFlush($product)
    {
        $this->em->persist($product);
        $this->em->flush();

        //The entity is updated then dispatch an event 
        $event = new GenericEvent($product, array('product_name' => 1));
        $this->dispatcher->dispatch('product', $event);
    }
}
<service id="yourdomain.event.update_product" class="Domain\YourBundle\EventListener\UpdateProductListener">

    <argument type="service" id="logger"/>
    <tag name="kernel.event_listener" event="product" method="onUpdateProduct"/>
</service>
namespace Domain\YourBundle\EventListener;

use Symfony\Component\EventDispatcher\GenericEvent;
use Domain\YourBundle\Entity\Product;
use Psr\Log\LoggerInterface;

class UpdateProductListener
{
    private $logger;

    /**
     * @param LoggerInterface $logger
     */
    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger;
    }
    /**
     * Listen the generic event dispatched when the product name is updated
     *
     * @param GenericEvent $event
     *
     * @throws RuntimeException
     * @throws \ErrorException
     */
    public function onUpdateProduct(GenericEvent $event)
    {
        if ($event->getSubject() instanceof Product) {
            $product = $event->getSubject();

            if ($event->hasArgument('product_name') && $event->getArgument('product_name') == 1) {
                /*
                Make your logic (send mail, add log, notification....)
                */
                $this->logger->notice('UpdateProductListener : event update product is occured');

            } else {
                $this->logger->notice('UpdateProductListener : event other than update product is occured.');
            }
        }
    }
}