Reputation: 563
I have an entity that has a OneToMany
relationship with another entity.
Meaning entity
/**
* One Meaning has Many Tags.
*
* @ORM\OneToMany(targetEntity="Tag", mappedBy="meaning")
*/
private $tags;
Tag entity
/**
* Many Tags have One Meaning.
*
* @ORM\ManyToOne(targetEntity="Meaning", inversedBy="tags")
* @ORM\JoinColumn(name="meaning_id", referencedColumnName="id")
*/
private $meaning;
I registered an event listener to the preUpdate
and prePersist
doctrine events.
services.yml
tag.event_listener.meaning_tag_persister:
class: TagBundle\EventListener\MeaningTagsPersister
tags:
- { name: doctrine.event_listener, event: preUpdate, method: preUpdate }
- { name: doctrine.event_listener, event: prePersist, method: prePersist }
Within this Event Listener all I do is set the meaning
in the tag
entity.
MeaningTagsPersister.php
/**
* Call before an entity gets updated
*
* @param PreUpdateEventArgs $args
*/
public function preUpdate(PreUpdateEventArgs $args)
{
/** @var Entry $object */
$object = $args->getObject();
if (!$object instanceof Meaning) {
return;
}
/** @var Tag $tag */
foreach($object->getTags() as $tag) {
$tag->setMeaning($object);
}
}
The prePersist
method looks exactly the same. Whenever I create a new Meaning
entity, the event listener gets called with the appropriate method. When I update the Meaning
entity the event listener works as well, but only if I update one of its "normal" properties like name
. If I change any of the tags
it is not recognized by doctrine
as a changed entity (which is correct as the Meaning
entity itself hasn't changed).
Yet, I still have to update the meaning
within each Tag
when the Meaning
entity gets updated. I also have to remove the meaning
from any Tag
that is no longer associated with that Meaning
.
Is an event listener the right way to accomplish this? If yes, how do I get the Meaning
entity to trigger the preUpdate
event if only the tags
have changed? If not, what would be the appropriate way to update all associated Tag
entities through the Meaning
entity?
Upvotes: 2
Views: 3374
Reputation: 46
The problem here is that PreUpdate
does not handle changes on Associations
as stated in the documentation:
...Changes to associations of the updated entity are never allowed in this event, since Doctrine cannot guarantee to correctly handle referential integrity at this point of the flush operation.
To verify, execute the same code in your Controller and it will persist the changes.
Upvotes: 3
Reputation: 1495
You are using doctrine Lifecycle Events you should add
/** @Entity @HasLifecycleCallbacks */
to your Meaning
and Tag
entities.
Refer: Doctrine Lifecycle Callbacks
Upvotes: 0