Doctrine packages have a rich event system that fires events when almost anything
happens inside the system. For you, this means that you can create arbitrary
services and tell Doctrine to notify those
objects whenever a certain action (e.g. prePersist()) happens within Doctrine.
This could be useful, for example, to create an independent search index
whenever an object in your database is saved.

Doctrine defines two types of objects that can listen to Doctrine events:
listeners and subscribers. Both are very similar, but listeners are a bit
more straightforward. For more, see The Event System on Doctrine's website.

The Doctrine website also explains all existing events that can be listened to.

To register a service to act as an event listener or subscriber you just have
to tag it with the appropriate name. Depending
on your use-case, you can hook a listener into every DBAL connection and ORM
entity manager or just into one specific DBAL connection and all the entity
managers that use this connection.

In the previous example, a SearchIndexer service was configured as a Doctrine
listener on the event postPersist. The class behind that service must have
a postPersist() 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

// src/AppBundle/EventListener/SearchIndexer.phpnamespaceAppBundle\EventListener;useDoctrine\ORM\Event\LifecycleEventArgs;useAppBundle\Entity\Product;classSearchIndexer{publicfunctionpostPersist(LifecycleEventArgs$args){$entity=$args->getEntity();// only act on some "Product" entityif(!$entityinstanceofProduct){return;}$entityManager=$args->getEntityManager();// ... do something with the Product}}

In each event, you have access to a LifecycleEventArgs object, which
gives you access to both the entity object of the event and the entity manager
itself.

One important thing to notice is that a listener will be listening for all
entities in your application. So, if you're interested in only handling a
specific type of entity (e.g. a Product entity but not a BlogPost
entity), you should check for the entity's class type in your method
(as shown above).

Tip

In Doctrine 2.4, a feature called Entity Listeners was introduced.
It is a lifecycle listener class used for an entity. You can read
about it in the Doctrine Documentation.

// src/AppBundle/EventListener/SearchIndexerSubscriber.phpnamespaceAppBundle\EventListener;useDoctrine\Common\EventSubscriber;// for Doctrine < 2.4: use Doctrine\ORM\Event\LifecycleEventArgs;useDoctrine\Common\Persistence\Event\LifecycleEventArgs;useAppBundle\Entity\Product;classSearchIndexerSubscriberimplementsEventSubscriber{publicfunctiongetSubscribedEvents(){returnarray('postPersist','postUpdate',);}publicfunctionpostUpdate(LifecycleEventArgs$args){$this->index($args);}publicfunctionpostPersist(LifecycleEventArgs$args){$this->index($args);}publicfunctionindex(LifecycleEventArgs$args){$entity=$args->getEntity();// perhaps you only want to act on some "Product" entityif($entityinstanceofProduct){$entityManager=$args->getEntityManager();// ... do something with the Product}}}

Tip

Doctrine event subscribers cannot return a flexible array of methods to
call for the events like the Symfony event subscriber
can. Doctrine event subscribers must return a simple array of the event
names they subscribe to. Doctrine will then expect methods on the subscriber
with the same name as each subscribed event, just as when using an event listener.

For a full reference, see chapter The Event System in the Doctrine documentation.

One subtle difference between listeners and subscribers is that Symfony can load
entity listeners lazily. This means that your listener class will only be fetched
from the service container (and thus be instantiated) once the event it is linked
to actually fires.

Lazy loading might give you a slight performance improvement when your listener
runs for events that rarely fire. Also, it can help you when you run into
circular dependency issues that may occur when your listener service in turn
depends on the DBAL connection.

To mark a listener service as lazily loaded, just add the lazy attribute
to the tag like so: