How to add entity event listeners¶
Used application: OroPlatform 1.7
In some cases, you need to update a field before saving or before updating an entity. A Doctrine Listener is a perfect way to do that.
Configuring the Listener¶
Suppose that you have already extended an Oro bundle like OroContactBundle
(you can find more information
in How to extend existing bundle).
And you would like to compliment your contact’s social information with some external API data.
For this you need to register your listener in the services.yml
file.
1 2 3 4 5 6 | # src/Acme/Bundle/ContactBundle/Resources/config/services.yml
services:
contact.listener:
class: Acme\Bundle\ContactBundle\Listener\SocialFields
tags:
- { name: doctrine.event_listener, event: onFlush }
|
Creating the Listener Class¶
In the previous part, we created the contact.listener that is triggered during the flush of en entity. In fact, the event will be triggered when all managed entities are being flushed, so you need to check the current entity class type.
This class must have the onFlush
method, which will be called when the event is dispatched:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <?php
// src/Acme/Bundle/ContactBundle/Listener/SocialFields.php
namespace Acme\Bundle\ContactBundle\Listener;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Oro\Bundle\ContactBundle\Entity\ContactEmail;
class SocialFields
{
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
// we would like to listen on insertions and updates events
$entities = array_merge(
$uow->getScheduledEntityInsertions(),
$uow->getScheduledEntityUpdates()
);
foreach ($entities as $entity) {
// every time we update or insert a new ContactEmail entity we do the work
if (!$entity instanceof ContactEmail) {
continue;
}
// check if email is primary
if ($entity->isPrimary()) {
$owner = $entity->getOwner();
// ... update social info of the owner with its primary email
// force persist
$em->persist($owner);
$md = $em->getClassMetadata(get_class($owner));
$uow->computeChangeSet($md, $owner);
}
}
}
}
|
Caution
In case of update, we need to persist the related entities and force update
them with computeChangeSet()
function. Every entity related to the current
one must be updated like this if you change any property values. If you
do not, the new value of your related entity’s property will not be updated.