I want that every time a new Distance
entity (from Place_A to Place_B) is saved, the reverse distance (from Place_B to Place_A) gets inserted too into the DB.
My problem is the following listener loops infinitely (hence the counter):
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();
}
}
}
}
Output:
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
It's like the original entity (creation time ending with 8787) was persisted an infinite number of times.
Just in case, if I remove the call to $em->flush
, I correctly get the following output:
Entity created at 1433167824.2552 is not reverse
Entity created at 1433167824.2947 is reverse
but then an exception saying that no parameters were bound to the insert query. Which is confirmed by Symfony's profiler:
INSERT INTO Distance (
miles, origin_id, destination_id
)
VALUES
(?, ?, ?)
Parameters: { }
I'd like to understand why my listener doesn't work as I expect, and how to fix it.
As requested, here's some more code. Everything comes from a Place
Form where, apart from entering the Place name, I can add/delete/edit a collection of distances to other Place
s.
// 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
]
]
);
}