问题描述
我们有三个实体:
- MaterialAssigned
- Stock
- 工作
MaterialAssigned
包含三个字段:
- 数量(int)
- 与
工作的关系
实体 - 与
股票
实体
- Quantity (int)
- Relation with a
Job
Entity - Relation with a
Stock
entity
的关系
我们正在尝试在MaterialAssigned上编写一个 preUpdate()
,它需要使用新的 Quantity
值,并做一些计算并更新相关 Stock
实体的总数量。
当我们按照逻辑选择 var_dump()
值时,一切似乎都按预期工作,但是相关的 Stock
实体永不更新。
We are try to write a preUpdate()
on MaterialAssigned which takes old and new Quantity
values, do some calculation and update the overall total quantity in the related Stock
Entity.When we var_dump()
values along our logic, everything seems to work as expected, however the related Stock
entity never gets updated.
这是EventListener的相关代码:
That's the relevant code from the EventListener:
public function preUpdate(PreUpdateEventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
if ($entity instanceof MaterialAssigned) {
$changeArray = $eventArgs->getEntityChangeSet();
$pre_quantity = $changeArray['quantity'][0];
$post_quantity = $changeArray['quantity'][1];
// Here we call the function to do the calculation, for testing we just use a fixed value
$entity->getStock()->setTotal(9999);
$em = $eventArgs->getEntityManager();
$uow = $em->getUnitOfWork();
$meta = $em->getClassMetadata(get_class($entity));
$uow->recomputeSingleEntityChangeSet($meta, $entity);
}
}
推荐答案
此处的问题是 preUpdate
受Doctrine的限制,不允许在此方法内更新任何实体。另一方面, onFlush
确实允许更新实体,并且不需要三种单独的方法(更新,持久性,删除)。
The issue here is that preUpdate
is restricted by Doctrine to not allow any Entities to be updated from within this method. onFlush
on the other hand does allow the update of Entities, and replaces the need for three separate methods (update, persist, remove).
然后,我们找到了以下指南,提示了解决方案:
We then found the following guide which hints at a solution: Tobias Sjösten's guide
我们的代码现在如下所示:
Our code now looks like:
public function onFlush(OnFlushEventArgs $args)
{
$this->em = $args->getEntityManager();
$uow = $this->em->getUnitOfWork();
// These collects an array of all the changes that are going to be flushed.
// If you do not wish to see deleted entities just remove the line $uow->getScheduledEntityDeletions()
$entities = array_merge(
$uow->getScheduledEntityInsertions(),
$uow->getScheduledEntityUpdates(),
$uow->getScheduledEntityDeletions()
);
foreach ($entities as $entity) {
if ($entity instanceof MaterialAssigned) {
// This gets an array filled with the changes for the entire entity
$changeArray = $uow->getEntityChangeSet($entity);
$stock = $entity->getStock();
// Here we call our function passing $changeArray.
// This does some math and update the value. For simplicity we just
// set the value manually in this example
$stock->setTotal(9999);
$md = $this->em->getClassMetadata('Northerncam\AppBundle\Entity\Stock');
$uow->recomputeSingleEntityChangeSet($md, $stock);
}
}
}
这是 print_r()
of $ changeArray
:
array (size=1)
'quantity' =>
array (size=2)
0 => int 10
1 => int 50
这篇关于symfony2更新eventListener中的相关实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!