nuc*_*tux 16 symfony doctrine-orm symfony-sonata
我想在实体持久化和更新上添加新的Feed项.我写这个事件监听器(postUpdate是一样的):
public function postPersist(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();
    $em = $args->getEntityManager();
    if ($entity instanceof FeedItemInterface) {
        $feed = new FeedEntity();
        $feed->setTitle($entity->getFeedTitle());
        $feed->setEntity($entity->getFeedEntityId());
        $feed->setType($entity->getFeedType());
        if($entity->isFeedTranslatable()) {
            $feed->getEnTranslation()->setTitle($entity->getFeedTitle('en'));
        }
        $em->persist($feed);
        $em->flush();
    }
}
但是我得到了
完整性约束违规:1062重复条目'30 -2'用于键'PRIMARY'
在日志中有两个插入:
INSERT INTO interview_scientificdirection(interview_id,scientificdirection_id)VALUES(?,?)([30,2])INSERT INTO interview_scientificdirection(interview_id,scientificdirection_id)VALUES(?,?)([30,2])
scientificdirection是多对多的关系表,对于我们想要坚持的实体.在前端应用程序一切正常,但在索纳塔管理员我遇到了这个问题:(
jho*_*ter 28
如果你需要保留其他对象,那么Doctrine中的postPersist或postUpdate处理程序可能不是正确的选择.我今天遇到了同样的问题,因为我需要在该处理程序中生成一些消息条目.
此时的问题是postPersist处理程序在 flush事件期间被调用,而不是之后.因此,您无法在此处保留其他对象,因为它们之后不会被刷新.此外,您不能在postPersist处理程序期间调用flush,因为这可能会导致ducplicate条目(正如您所经历的那样).
一种方法是使用doctrine中的onFlush处理程序,在此处记录:http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#onflush
如果您需要插入数据库对象的ID,这只是有问题的,因为该实体尚未写入该处理程序中的数据库.如果你不需要那些id,你可以在教义中使用ofFlush事件.
对我来说,解决方案有点不同.我目前正在研究一个symfony2项目,并且需要插入数据库对象的ID(稍后用于回调和更新).
我在symfony2中创建了一个新服务,它基本上就像我的消息队列一样.在postPersist更新期间,我只填写队列中的条目.我在kernel.response其上注册了另一个处理程序,然后获取这些条目并将它们持久保存到数据库中.(有关这方面的内容:http://symfony.com/doc/current/cookbook/service_container/event_listener.html)
我希望我不要在这里偏离这个主题,但是因为这是我真正努力的事情,我希望有些人可能会觉得这很有用.
这方面的服务条目是:
 amq_messages_chain:
   class: Acme\StoreBundle\Listener\AmqMessagesChain
 amqflush:
   class: Acme\StoreBundle\Listener\AmqFlush
   arguments: [ @doctrine.orm.entity_manager, @amq_messages_chain, @logger ]
   tags:
     - { name: kernel.event_listener, event: kernel.response, method: onResponse, priority: 5 }
 doctrine.listener:
  class: Acme\StoreBundle\Listener\AmqListener
  arguments: [ @logger, @amq_messages_chain ]
  tags:
    - { name: doctrine.event_listener, event: postPersist }
    - { name: doctrine.event_listener, event: postUpdate }
    - { name: doctrine.event_listener, event: prePersist }
您不能使用doctrine.listenerfor,因为这会导致循环依赖(因为您需要服务的实体管理器,但实体管理器需要服务....)
这就像一个魅力.如果您需要更多信息,请不要犹豫,我很高兴为此添加一些示例.
小智 27
Francesc的答案是错误的,因为postFlush事件中的变更集已经为空.jhoffrichter的第二个答案可行,但是有点矫枉过正.正确的方法是将实体持久化在postPersist事件中,并在postFlush事件中再次调用flush.但是,只有在postPersist事件中更改了某些内容时才必须执行此操作,否则您将创建无限循环.
public function postPersist(LifecycleEventArgs $args) {
    $entity = $args->getEntity();
    $em = $args->getEntityManager();
    if($entity instanceof FeedItemInterface) {
        $feed = new FeedEntity();
        $feed->setTitle($entity->getFeedTitle());
        $feed->setEntity($entity->getFeedEntityId());
        $feed->setType($entity->getFeedType());
        if($entity->isFeedTranslatable()) {
            $feed->getEnTranslation()->setTitle($entity->getFeedTitle('en'));
        }
        $em->persist($feed);
        $this->needsFlush = true;
    }
}
public function postFlush(PostFlushEventArgs $eventArgs)
{
    if ($this->needsFlush) {
        $this->needsFlush = false;
        $eventArgs->getEntityManager()->flush();
    }
}
| 归档时间: | 
 | 
| 查看次数: | 35267 次 | 
| 最近记录: |