sajad torkamani

In a nutshell

Doctrine ORM provides a lightweight event system that lets you register custom event listeners / subscribers that hook into various lifecycle events (e.g., prePersist, postPersist, preUpdate, etc).

List of events

EventDispatched byLifecycle CallbackPassed Argument
preRemove$em->remove()YesLifecycleEventArgs
postRemove$em->flush()YesLifecycleEventArgs
prePersist$em->persist() on initial persistYesLifecycleEventArgs
postPersist$em->flush()YesLifecycleEventArgs
preUpdate$em->flush()YesPreUpdateEventArgs
postUpdate$em->flush()YesLifecycleEventArgs
postLoadLoading from databaseYesLifecycleEventArgs
loadClassMetadataLoading of mapping metadataNoLoadClassMetadataEventArgs
onClassMetadataNotFoundMappingExceptionNoOnClassMetadataNotFoundEventArgs
preFlush$em->flush()YesPreFlushEventArgs
onFlush$em->flush()NoOnFlushEventArgs
postFlush$em->flush()NoPostFlushEventArgs
onClear$em->clear()NoOnClearEventArgs

prePersist

Called when:

  1. You explicitly call EntityManager:persist(). Also called for cascaded associations.
  2. Inside the flush() method if the entity is a new entity (either standalone or as an association).

prePersist is only invoked on initial persist of an entity, not on future updates.

postPersist

Called after the entity has been made persistent. Invoked after the database insert operations. Generated primary key values are available in the postPersist event.

onFlush

Called inside EntityManager::flush() after all the changes to managed entities and their associations have been computed. The onFlush event has access to the:

  • Entities scheduled for insert
  • Entities scheduled for update
  • Entities scheduled for removal
  • Collections scheduled for update
  • Collections scheduled for removal

Here’s an example usage of the onFlush event:

<?php
class FlushExampleListener
{
    public function onFlush(OnFlushEventArgs $eventArgs)
    {
        $em = $eventArgs->getEntityManager();
        $uow = $em->getUnitOfWork();

        foreach ($uow->getScheduledEntityInsertions() as $entity) {

        }

        foreach ($uow->getScheduledEntityUpdates() as $entity) {

        }

        foreach ($uow->getScheduledEntityDeletions() as $entity) {

        }

        foreach ($uow->getScheduledCollectionDeletions() as $col) {

        }

        foreach ($uow->getScheduledCollectionUpdates() as $col) {

        }
    }
}

Recipes

Register event listeners

<?php
class TestEvent
{
    const preFoo = 'preFoo';
    const postFoo = 'postFoo';

    private $_evm;

    public $preFooInvoked = false;
    public $postFooInvoked = false;

    public function __construct($evm)
    {
        $evm->addEventListener(array(self::preFoo, self::postFoo), $this);
    }

    public function preFoo(EventArgs $e)
    {
        $this->preFooInvoked = true;
    }

    public function postFoo(EventArgs $e)
    {
        $this->postFooInvoked = true;
    }
}

// Create a new instance
$test = new TestEvent($evm);

Dispatch events

<?php
$evm->dispatchEvent(TestEvent::preFoo);
$evm->dispatchEvent(TestEvent::postFoo);

Create event subscriber

You can also write your event handling logic in the form of event subscribers that implement the \Doctrine\Common\EventSubscriber interface.

<?php
use Doctrine\Common\EventSubscriber;

class TestEventSubscriber implements EventSubscriber
{
    public $preFooInvoked = false;

    public function preFoo()
    {
        $this->preFooInvoked = true;
    }

    public function getSubscribedEvents()
    {
        return array(TestEvent::preFoo);
    }
}

$eventSubscriber = new TestEventSubscriber();
$evm->addEventSubscriber($eventSubscriber);

The getSubscribedEvents() method must return an array where each value represents the event name and a method (named exactly the same) that subscribes to that event.

Sources

Tagged: Doctrine