【问题标题】:Symfony2 - EventListener changing data onFlushSymfony2 - EventListener 改变数据 onFlush
【发布时间】:2013-10-28 13:51:58
【问题描述】:

我正在尝试使用 KnpSnappyBundle 生成 Pdf,并在生成我的 Bill 实体时将位置保存在学说中。

为此,我需要打版服务,但我无法进入实体。

我阅读了 EventListener 并试图让一个工作。

我的 config.yml

services:
    bill.listener:
        class: MyCompany\CompanyBundle\EventListener\BillListener
        tags:
            - { name: doctrine.event_listener, event: onFlush }

还有我的听众

namespace MyCompany\CompanyBundle\EventListener;

use Doctrine\ORM\Event\OnFlushEventArgs;

class BillListener
{
    public function onFlush(OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        foreach ($uow->getScheduledEntityInsertions() as $insertions) {
            foreach ($insertions as $entity) {
                if ($entity instanceof Bill) {
                    $entity->setFilename("test.pdf");

                    $md = $em->getClassMetadata(get_class($entity));
                    $uow->recomputeSingleEntityChangeSet($md, $entity);
                }
            }
        }
    }
}

我的账单实体有一个 setFilename 函数,我想在其中保存生成的账单的位置。但我什至无法让它工作。

【问题讨论】:

  • 嗨,我想你忘记了 Bill 类的命名空间

标签: symfony doctrine-orm event-listener


【解决方案1】:

不要再搞乱 UOW(这是一种黑客行为),再次刷新它:

配置

services:
    bill.listener:
        class: MyCompany\CompanyBundle\EventListener\BillListener
        arguments: ["@pdf_service"]
        tags :
            - { name: doctrine.event_subscriber, connection: default }

听众

<?php

namespace MyCompany\CompanyBundle\EventListener;

use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;

use MyCompany\CompanyBundle\Service\MyPDFService;
use MyCompany\CompanyBundle\Entity\Bill;

class BillListener implements EventSubscriber
{
    protected $pdfs;
    protected $bills;

    public function __construct(MyPDFService $pdfs)
    {
        $this->pdfs = $pdfs;
    }

    public function getSubscribedEvents()
    {
        return [
            'onFlush',
            'postFlush'
        ];
    }

    public function onFlush(OnFlushEventArgs $event)
    {
        $this->bills = [];
        /* @var $em \Doctrine\ORM\EntityManager */
        $em = $event->getEntityManager();
        /* @var $uow \Doctrine\ORM\UnitOfWork */
        $uow = $em->getUnitOfWork();

        foreach ($uow->getScheduledEntityInsertions() as $entity) {

            if ($entity instanceof Bill) {

                $this->bills[] = $entity;
            }
        }
    }

    public function postFlush(PostFlushEventArgs $event)
    {
        if (!empty($this->bills)) {

            /* @var $em \Doctrine\ORM\EntityManager */
            $em = $event->getEntityManager();

            foreach ($this->bills as $bill) {

                /* @var $bill \MyCompany\CompanyBundle\Entity\Bill */
                $this->pdfs->generateFor($bill);
                $em->persist($bill);
            }

            $em->flush();
        }
    }
}

【讨论】:

  • 对我有用。必须更改 getSubscribedEvents 函数以返回数组('onFlush', 'postFlush');
  • 对不起,但是......“插入”只发生一次,第一次持久化实体。无论如何,使用某些属性作为标志可以避免循环。
  • 这个解决方案不会破坏操作的原子性吗?如果第二次刷新失败怎么办?好的,在这种情况下,不会生成 PDF,但是如果第二次刷新应该是一件非常重要的事情呢?这会导致不一致吗?
  • 好吧,那么你应该照顾好它,也许在这种情况下,你真正需要的是一项服务,以你想要的方式管理你的操作,只需在一个事务中。
  • 似乎在 postFlush 中调用 flush() 不是一个好主意“EntityManager#flush() 不能在内部安全地调用”:docs.doctrine-project.org/projects/doctrine-orm/en/latest/…
猜你喜欢
  • 2017-03-27
  • 2018-12-27
  • 2015-09-29
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多