【发布时间】:2015-08-15 01:47:37
【问题描述】:
我希望每次保存一个新的Distance 实体(从 Place_A 到 Place_B)时,反向距离(从 Place_B 到 Place_A)gets inserted too into the DB。
我的问题是以下监听器无限循环(因此是计数器):
class Listener
{
public $count;
public function prePersist(LifecycleEventArgs $eventArgs)
{
if ($this->count > 5) {
die();
}
$entity = $eventArgs->getEntity();
if ($entity instanceof Distance) {
// $this->created = microtime(true) in Distance's constructor
echo 'Entity created at ' . $entity->created;
if ($entity->isReverse) {
echo " is reverse\n";
} else {
echo " is not reverse\n";
$this->count++;
$reverse = new Distance();
$reverse->setOrigin($entity->getDestination());
$reverse->setDestination($entity->getOrigin());
$reverse->set($entity->getMiles());
$reverse->isReverse = true;
$em = $eventArgs->getEntityManager();
$em->persist($reverse);
$em->flush();
}
}
}
}
输出:
Entity created at 1433168310.8787 is not reverse
Entity created at 1433168310.9073 is reverse
Entity created at 1433168310.8787 is not reverse
Entity created at 1433168310.9078 is reverse
Entity created at 1433168310.8787 is not reverse
Entity created at 1433168310.908 is reverse
Entity created at 1433168310.8787 is not reverse
Entity created at 1433168310.9084 is reverse
Entity created at 1433168310.8787 is not reverse
Entity created at 1433168310.9087 is reverse
Entity created at 1433168310.8787 is not reverse
就像原始实体(创建时间以 8787 结尾)被无限次保留。
以防万一,如果我删除对$em->flush 的调用,我会正确得到以下输出:
Entity created at 1433167824.2552 is not reverse
Entity created at 1433167824.2947 is reverse
但随后出现异常,表示没有参数绑定到插入查询。 Symfony 的分析器证实了这一点:
INSERT INTO Distance (
miles, origin_id, destination_id
)
VALUES
(?, ?, ?)
Parameters: { }
我想了解为什么我的监听器不能按我的预期工作,以及如何解决它。
根据要求,这里还有一些代码。一切都来自Place 表单,除了输入地名之外,我还可以添加/删除/编辑与其他Places 的距离集合。
// PlaceController::updateAction
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('MyBundle:Place')->find($id);
if (! $entity) {
throw $this->createNotFoundException('Unable to find Place entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createForm(new PlaceType(), $entity, array(
'action' => $this->generateUrl('update_place', array('id' => $entity->getId())),
'method' => 'PUT'
));
$editForm->add('submit', 'submit', array('label' => 'panel.button.save'));
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return array(
'entity' => $entity,
'form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
// PlaceType::buildForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$Place = $builder->getData();
$builder
->add(
'name',
'text',
[
'label' => 'object.place.name'
]
)
->add(
'distancesTo',
'collection',
[
'label' => 'object.place.distance.plural',
'type' => new DistanceType(),
'by_reference' => false,
'allow_add' => true,
'allow_delete' => true,
'options' => [
'required' => false,
'origin' => $Place->getId() ? $Place : null
]
]
);
}
【问题讨论】:
-
首先你不应该在那里调用
$em->flush(),因为在 prePersist 块中刷新是不好的形式,因为实体管理器可能会在原始位置被刷新坚持。 -
你能在原始实体被持久化的地方添加代码吗?
-
@Decave 保留原始距离实体的代码不是我的。正如我在编辑中解释的那样,它在持久保存父 Place 实体(关联上的
cascade:{"persist"})时会自动发生。
标签: php symfony orm doctrine-orm doctrine