Registering Event Listeners and Subscribers¶
Doctrine packages 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.
Configuring the Listener/Subscriber¶
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.
- YAML
doctrine: dbal: default_connection: default connections: default: driver: pdo_sqlite memory: true services: my.listener: class: Acme\SearchBundle\Listener\SearchIndexer tags: - { name: doctrine.event_listener, event: postPersist } my.listener2: class: Acme\SearchBundle\Listener\SearchIndexer2 tags: - { name: doctrine.event_listener, event: postPersist, connection: default } my.subscriber: class: Acme\SearchBundle\Listener\SearchIndexerSubscriber tags: - { name: doctrine.event_subscriber, connection: default }
- XML
<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:doctrine="http://symfony.com/schema/dic/doctrine"> <doctrine:config> <doctrine:dbal default-connection="default"> <doctrine:connection driver="pdo_sqlite" memory="true" /> </doctrine:dbal> </doctrine:config> <services> <service id="my.listener" class="Acme\SearchBundle\Listener\SearchIndexer"> <tag name="doctrine.event_listener" event="postPersist" /> </service> <service id="my.listener2" class="Acme\SearchBundle\Listener\SearchIndexer2"> <tag name="doctrine.event_listener" event="postPersist" connection="default" /> </service> <service id="my.subscriber" class="Acme\SearchBundle\Listener\SearchIndexerSubscriber"> <tag name="doctrine.event_subscriber" connection="default" /> </service> </services> </container>
Creating the Listener Class¶
In the previous example, a service my.listener
was configured as a Doctrine
listener on the event postPersist
. That class behind that service must have
a postPersist
method, which will be called when the event is thrown:
// src/Acme/SearchBundle/Listener/SearchIndexer.php
namespace Acme\SearchBundle\Listener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Acme\StoreBundle\Entity\Product;
class SearchIndexer
{
public function postPersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$entityManager = $args->getEntityManager();
// perhaps you only want to act on some "Product" entity
if ($entity instanceof Product) {
// 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 class name of the entity in your method
(as shown above).