在Doctrine 2(和Symfony)中正确使用$ unitOfWork-> getScheduledCollectionDeletions()是什么?

时间:2013-03-09 13:14:15

标签: symfony doctrine-orm doctrine

我正在尝试检测onFlush事件中多对多关系的变化。

如果将新实体添加到关系中或更新关系(始终保留元素),我可以使用$unitOfWork->getScheduledCollectionUpdates()检测更改,然后检查getInsertDiff()getDeleteDiff()。到目前为止一切都很好。

当我从关系中取出所有实体时出现问题:“之前有两个相关实体,但现在有 NO 相关实体。”

当关系为空时,我可以访问$unitOfWork->getScheduledCollectionDeletions(),但无法知道删除了哪些实体:

  • getDeleteDiff()这个系列没有任何说明。
  • getSnapshot()并未告诉我
  • 之前有哪些实体

我应该如何知道哪些实体脱离了多对多关系?


我添加了一个完整实现的Gist:一切正常(可能需要一些优化),$uow->getScheduledCollectionDeletions()除外(第101行)

  

https://gist.github.com/eillarra/5127606

1 个答案:

答案 0 :(得分:6)

此问题的原因是双重的:

1)在clear()上调用方法Doctrine\ORM\PersistentCollection时,它会:

  1. 清除其内部实体集合。
  2. 致电scheduleCollectionDeletion()上的Doctrine\ORM\UnitOfWork
  3. 拍摄自己的新照片。
  4. 第2号是您的收藏集显示在$uow->getScheduledCollectionDeletions()(而不是$uow->getScheduledCollectionUpdates())中的原因。数字3是您在清除之前无法确定集合中的内容的原因。

    2)当使用Symfony2表单组件,特别是ChoiceTypeCollectionType类型与选项multiple结合使用时,{em} clear()方法将在应从集合中删除所有实体。

    这是由于此处添加了MergeDoctrineCollectionListenerhttps://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php#L55

    这是作为优化完成的:以这种方式清除集合的速度更快,而不是检查应从中删除哪些实体。

    我可以想到两个可能的解决方案

    1)创建一个分叉symfony/symfony并实现一个选项,以便添加MergeDoctrineCollectionListener。也许像no_clear之类的东西可以防止添加监听器。这不会引入BC中断并且会解决您的问题,因为当所有实体都应该被删除时,不会调用集合的clear()方法。

    2)重新设计您的计数器:也许还会收听OnLoad事件,该事件可以计算从数据库中提取时集合中实体的数量。这样,您的OnFlush侦听器就可以使用该数字来了解清除时从集合中删除的实体数量。